CS5500
nuklear.h
Go to the documentation of this file.
1#ifndef NK_SINGLE_HEADER
2#define NK_SINGLE_HEADER
3#ifndef NK_NUKLEAR_H_
4#define NK_NUKLEAR_H_
5
6#ifdef __cplusplus
7extern "C" {
8#endif
9/*
10 * ==============================================================
11 *
12 * CONSTANTS
13 *
14 * ===============================================================
15 */
16#define NK_UNDEFINED (-1.0f)
17#define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
18#define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
19#ifndef NK_INPUT_MAX
20 #define NK_INPUT_MAX 16
21#endif
22#ifndef NK_MAX_NUMBER_BUFFER
23 #define NK_MAX_NUMBER_BUFFER 64
24#endif
25#ifndef NK_SCROLLBAR_HIDING_TIMEOUT
26 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
27#endif
28/*
29 * ==============================================================
30 *
31 * HELPER
32 *
33 * ===============================================================
34 */
35#ifndef NK_API
36 #ifdef NK_PRIVATE
37 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
38 #define NK_API static inline
39 #elif defined(__cplusplus)
40 #define NK_API static inline
41 #else
42 #define NK_API static
43 #endif
44 #else
45 #define NK_API extern
46 #endif
47#endif
48#ifndef NK_LIB
49 #ifdef NK_SINGLE_FILE
50 #define NK_LIB static
51 #else
52 #define NK_LIB extern
53 #endif
54#endif
55
56#define NK_INTERN static
57#define NK_STORAGE static
58#define NK_GLOBAL static
59
60#define NK_FLAG(x) (1 << (x))
61#define NK_STRINGIFY(x) #x
62#define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
63#define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
64#define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
65#define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
66
67#ifdef _MSC_VER
68 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
69#else
70 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
71#endif
72
73#ifndef NK_STATIC_ASSERT
74 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
75#endif
76
77#ifndef NK_FILE_LINE
78#ifdef _MSC_VER
79 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
80#else
81 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
82#endif
83#endif
84
85#define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
86#define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
87#define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
88
89#ifdef NK_INCLUDE_STANDARD_VARARGS
90 #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
91 #include <sal.h>
92 #define NK_PRINTF_FORMAT_STRING _Printf_format_string_
93 #else
94 #define NK_PRINTF_FORMAT_STRING
95 #endif
96 #if defined(__GNUC__)
97 #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1)))
98 #define NK_PRINTF_VALIST_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, 0)))
99 #else
100 #define NK_PRINTF_VARARG_FUNC(fmtargnumber)
101 #define NK_PRINTF_VALIST_FUNC(fmtargnumber)
102 #endif
103#endif
104
105/*
106 * ===============================================================
107 *
108 * BASIC
109 *
110 * ===============================================================
111 */
112#ifdef NK_INCLUDE_FIXED_TYPES
113 #include <stdint.h>
114 #define NK_INT8 int8_t
115 #define NK_UINT8 uint8_t
116 #define NK_INT16 int16_t
117 #define NK_UINT16 uint16_t
118 #define NK_INT32 int32_t
119 #define NK_UINT32 uint32_t
120 #define NK_SIZE_TYPE uintptr_t
121 #define NK_POINTER_TYPE uintptr_t
122#else
123 #ifndef NK_INT8
124 #define NK_INT8 signed char
125 #endif
126 #ifndef NK_UINT8
127 #define NK_UINT8 unsigned char
128 #endif
129 #ifndef NK_INT16
130 #define NK_INT16 signed short
131 #endif
132 #ifndef NK_UINT16
133 #define NK_UINT16 unsigned short
134 #endif
135 #ifndef NK_INT32
136 #if defined(_MSC_VER)
137 #define NK_INT32 __int32
138 #else
139 #define NK_INT32 signed int
140 #endif
141 #endif
142 #ifndef NK_UINT32
143 #if defined(_MSC_VER)
144 #define NK_UINT32 unsigned __int32
145 #else
146 #define NK_UINT32 unsigned int
147 #endif
148 #endif
149 #ifndef NK_SIZE_TYPE
150 #if defined(_WIN64) && defined(_MSC_VER)
151 #define NK_SIZE_TYPE unsigned __int64
152 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
153 #define NK_SIZE_TYPE unsigned __int32
154 #elif defined(__GNUC__) || defined(__clang__)
155 #if defined(__x86_64__) || defined(__ppc64__)
156 #define NK_SIZE_TYPE unsigned long
157 #else
158 #define NK_SIZE_TYPE unsigned int
159 #endif
160 #else
161 #define NK_SIZE_TYPE unsigned long
162 #endif
163 #endif
164 #ifndef NK_POINTER_TYPE
165 #if defined(_WIN64) && defined(_MSC_VER)
166 #define NK_POINTER_TYPE unsigned __int64
167 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
168 #define NK_POINTER_TYPE unsigned __int32
169 #elif defined(__GNUC__) || defined(__clang__)
170 #if defined(__x86_64__) || defined(__ppc64__)
171 #define NK_POINTER_TYPE unsigned long
172 #else
173 #define NK_POINTER_TYPE unsigned int
174 #endif
175 #else
176 #define NK_POINTER_TYPE unsigned long
177 #endif
178 #endif
179#endif
180
190
194
195/* Make sure correct type size:
196 * This will fire with a negative subscript error if the type sizes
197 * are set incorrectly by the compiler, and compile out if not */
204NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
205NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
206NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
207
208/* ============================================================================
209 *
210 * API
211 *
212 * =========================================================================== */
213struct nk_buffer;
214struct nk_allocator;
215struct nk_command_buffer;
216struct nk_draw_command;
217struct nk_convert_config;
218struct nk_style_item;
219struct nk_text_edit;
220struct nk_draw_list;
221struct nk_user_font;
222struct nk_panel;
223struct nk_context;
224struct nk_draw_vertex_layout_element;
225struct nk_style_button;
226struct nk_style_toggle;
228struct nk_style_slide;
229struct nk_style_progress;
230struct nk_style_scrollbar;
231struct nk_style_edit;
232struct nk_style_property;
233struct nk_style_chart;
234struct nk_style_combo;
235struct nk_style_tab;
237struct nk_style_window;
238
240struct nk_color {nk_byte r,g,b,a;};
241struct nk_colorf {float r,g,b,a;};
242struct nk_vec2 {float x,y;};
243struct nk_vec2i {short x, y;};
244struct nk_rect {float x,y,w,h;};
245struct nk_recti {short x,y,w,h;};
246typedef char nk_glyph[NK_UTF_SIZE];
247typedef union {void *ptr; int id;} nk_handle;
248struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
249struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
250struct nk_scroll {nk_uint x, y;};
251
264
265typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
266typedef void (*nk_plugin_free)(nk_handle, void *old);
267typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
268typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
269typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
270
275};
292/* =============================================================================
293 *
294 * CONTEXT
295 *
296 * =============================================================================*/
297/*/// ### Context
329 */
330#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
331/*/// #### nk_init_default
346*/
347NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
348#endif
349/*/// #### nk_init_fixed
371*/
372NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
373/*/// #### nk_init
389*/
390NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
391/*/// #### nk_init_custom
408*/
409NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
410/*/// #### nk_clear
422*/
424/*/// #### nk_free
435*/
437#ifdef NK_INCLUDE_COMMAND_USERDATA
438/*/// #### nk_set_user_data
449*/
450NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
451#endif
452/* =============================================================================
453 *
454 * INPUT
455 *
456 * =============================================================================*/
457/*/// ### Input
517*/
533 /* Shortcuts: text field */
546 /* Shortcuts: scrollbar */
560/*/// #### nk_input_begin
571*/
573/*/// #### nk_input_motion
585*/
586NK_API void nk_input_motion(struct nk_context*, int x, int y);
587/*/// #### nk_input_key
599*/
600NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
601/*/// #### nk_input_button
615*/
616NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
617/*/// #### nk_input_scroll
630*/
631NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
632/*/// #### nk_input_char
648*/
649NK_API void nk_input_char(struct nk_context*, char);
650/*/// #### nk_input_glyph
665*/
667/*/// #### nk_input_unicode
681*/
683/*/// #### nk_input_end
694*/
696/* =============================================================================
697 *
698 * DRAWING
699 *
700 * =============================================================================*/
701/*/// ### Drawing
924*/
934 nk_handle texture; /* texture handle to a texture with a white pixel */
935 struct nk_vec2 uv; /* coordinates to a white pixel in the texture */
936};
938 float global_alpha; /* global alpha value */
939 enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
940 enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
941 unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
942 unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
943 unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
944 struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
945 const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
946 nk_size vertex_size; /* sizeof one vertex for vertex packing */
947 nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
948};
949/*/// #### nk__begin
962*/
963NK_API const struct nk_command* nk__begin(struct nk_context*);
964/*/// #### nk__next
977*/
978NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
979/*/// #### nk_foreach
992*/
993#define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
994#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
995/*/// #### nk_convert
1023*/
1024NK_API nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
1025/*/// #### nk__draw_begin
1038*/
1039NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1040/*/// #### nk__draw_end
1053*/
1054NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1055/*/// #### nk__draw_next
1069*/
1070NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1071/*/// #### nk_draw_foreach
1083*/
1084#define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1085#endif
1086/* =============================================================================
1087 *
1088 * WINDOW
1089 *
1090 * =============================================================================
1175//
1197//
1203//
1209*/
1210/*
1232*/
1246/*/// #### nk_begin
1263*/
1264NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1265/*/// #### nk_begin_titled
1283*/
1284NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1285/*/// #### nk_end
1296*/
1297NK_API void nk_end(struct nk_context *ctx);
1298/*/// #### nk_window_find
1312*/
1313NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1314/*/// #### nk_window_get_bounds
1328*/
1330/*/// #### nk_window_get_position
1344*/
1346/*/// #### nk_window_get_size
1360*/
1362/*/// #### nk_window_get_width
1376*/
1378/*/// #### nk_window_get_height
1392*/
1394/*/// #### nk_window_get_panel
1410*/
1412/*/// #### nk_window_get_content_region
1429*/
1431/*/// #### nk_window_get_content_region_min
1448*/
1450/*/// #### nk_window_get_content_region_max
1467*/
1469/*/// #### nk_window_get_content_region_size
1485*/
1487/*/// #### nk_window_get_canvas
1504*/
1506/*/// #### nk_window_get_scroll
1520*/
1521NK_API void nk_window_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y);
1522/*/// #### nk_window_has_focus
1535*/
1537/*/// #### nk_window_is_hovered
1550*/
1552/*/// #### nk_window_is_collapsed
1565*/
1566NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1567/*/// #### nk_window_is_closed
1579*/
1580NK_API int nk_window_is_closed(struct nk_context*, const char*);
1581/*/// #### nk_window_is_hidden
1593*/
1594NK_API int nk_window_is_hidden(struct nk_context*, const char*);
1595/*/// #### nk_window_is_active
1607*/
1608NK_API int nk_window_is_active(struct nk_context*, const char*);
1609/*/// #### nk_window_is_any_hovered
1620*/
1622/*/// #### nk_item_is_any_active
1635*/
1637/*/// #### nk_window_set_bounds
1648*/
1649NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
1650/*/// #### nk_window_set_position
1661*/
1662NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
1663/*/// #### nk_window_set_size
1674*/
1675NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
1676/*/// #### nk_window_set_focus
1686*/
1687NK_API void nk_window_set_focus(struct nk_context*, const char *name);
1688/*/// #### nk_window_set_scroll
1702*/
1703NK_API void nk_window_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y);
1704/*/// #### nk_window_close
1714*/
1715NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1716/*/// #### nk_window_collapse
1727*/
1728NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1729/*/// #### nk_window_collapse_if
1741*/
1742NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1743/*/// #### nk_window_show
1754*/
1755NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1756/*/// #### nk_window_show_if
1768*/
1769NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1770/* =============================================================================
1771 *
1772 * LAYOUT
1773 *
1774 * =============================================================================
2019//
2026//
2032//
2036//
2042*/
2043/*/// #### nk_layout_set_min_row_height
2057*/
2059/*/// #### nk_layout_reset_min_row_height
2068*/
2070/*/// #### nk_layout_widget_bounds
2081*/
2083/*/// #### nk_layout_ratio_from_pixel
2095*/
2096NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
2097/*/// #### nk_layout_row_dynamic
2110*/
2111NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
2112/*/// #### nk_layout_row_static
2126*/
2127NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
2128/*/// #### nk_layout_row_begin
2140*/
2141NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
2142/*/// #### nk_layout_row_push
2152*/
2153NK_API void nk_layout_row_push(struct nk_context*, float value);
2154/*/// #### nk_layout_row_end
2163*/
2165/*/// #### nk_layout_row
2177*/
2178NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
2179/*/// #### nk_layout_row_template_begin
2189*/
2190NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
2191/*/// #### nk_layout_row_template_push_dynamic
2201*/
2203/*/// #### nk_layout_row_template_push_variable
2213*/
2215/*/// #### nk_layout_row_template_push_static
2225*/
2227/*/// #### nk_layout_row_template_end
2236*/
2238/*/// #### nk_layout_space_begin
2250*/
2251NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
2252/*/// #### nk_layout_space_push
2262*/
2263NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds);
2264/*/// #### nk_layout_space_end
2273*/
2275/*/// #### nk_layout_space_bounds
2286*/
2288/*/// #### nk_layout_space_to_screen
2300*/
2302/*/// #### nk_layout_space_to_local
2314*/
2316/*/// #### nk_layout_space_rect_to_screen
2328*/
2330/*/// #### nk_layout_space_rect_to_local
2342*/
2344/* =============================================================================
2345 *
2346 * GROUP
2347 *
2348 * =============================================================================
2431*/
2432/*/// #### nk_group_begin
2445*/
2446NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
2447/*/// #### nk_group_begin_titled
2461*/
2462NK_API int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
2463/*/// #### nk_group_end
2472*/
2474/*/// #### nk_group_scrolled_offset_begin
2490*/
2491NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
2492/*/// #### nk_group_scrolled_begin
2507*/
2508NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
2509/*/// #### nk_group_scrolled_end
2518*/
2520/*/// #### nk_group_get_scroll
2532*/
2533NK_API void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset);
2534/*/// #### nk_group_set_scroll
2546*/
2547NK_API void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset);
2548/* =============================================================================
2549 *
2550 * TREE
2551 *
2552 * =============================================================================
2607//
2617*/
2618/*/// #### nk_tree_push
2638*/
2639#define nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
2640/*/// #### nk_tree_push_id
2655*/
2656#define nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
2657/*/// #### nk_tree_push_hashed
2675*/
2676NK_API int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
2677/*/// #### nk_tree_image_push
2688//
2698*/
2699#define nk_tree_image_push(ctx, type, img, title, state) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
2700/*/// #### nk_tree_image_push_id
2718*/
2719#define nk_tree_image_push_id(ctx, type, img, title, state, id) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
2720/*/// #### nk_tree_image_push_hashed
2739*/
2740NK_API int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
2741/*/// #### nk_tree_pop
2750*/
2752/*/// #### nk_tree_state_push
2766*/
2767NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
2768/*/// #### nk_tree_state_image_push
2783*/
2784NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
2785/*/// #### nk_tree_state_pop
2794*/
2796
2797#define nk_tree_element_push(ctx, type, title, state, sel) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
2798#define nk_tree_element_push_id(ctx, type, title, state, sel, id) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
2799NK_API int nk_tree_element_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len, int seed);
2800NK_API int nk_tree_element_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len,int seed);
2802
2803/* =============================================================================
2804 *
2805 * LIST VIEW
2806 *
2807 * ============================================================================= */
2809/* public: */
2811/* private: */
2816};
2817NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
2819/* =============================================================================
2820 *
2821 * WIDGET
2822 *
2823 * ============================================================================= */
2825 NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
2826 NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
2827 NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
2831 NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */
2832 NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */
2833 NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */
2834 NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */
2835 NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
2837 NK_WIDGET_STATE_ACTIVE = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */
2849NK_API void nk_spacing(struct nk_context*, int cols);
2850/* =============================================================================
2851 *
2852 * TEXT
2853 *
2854 * ============================================================================= */
2868NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
2869NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
2870NK_API void nk_text_wrap(struct nk_context*, const char*, int);
2871NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
2872NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
2873NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
2874NK_API void nk_label_wrap(struct nk_context*, const char*);
2875NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
2876NK_API void nk_image(struct nk_context*, struct nk_image);
2877NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color);
2878#ifdef NK_INCLUDE_STANDARD_VARARGS
2879NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3);
2880NK_API void nk_labelf_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(4);
2881NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2);
2882NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3);
2883NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
2884NK_API void nk_labelfv_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(4);
2885NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
2886NK_API void nk_labelfv_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
2887NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
2888NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
2889NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
2890NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
2891NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
2892NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
2893NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
2894#endif
2895/* =============================================================================
2896 *
2897 * BUTTON
2898 *
2899 * ============================================================================= */
2900NK_API int nk_button_text(struct nk_context*, const char *title, int len);
2901NK_API int nk_button_label(struct nk_context*, const char *title);
2905NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
2906NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2907NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
2908NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
2909NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
2910NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
2912NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
2913NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2914NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align);
2915NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
2916NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
2920/* =============================================================================
2921 *
2922 * CHECKBOX
2923 *
2924 * ============================================================================= */
2925NK_API int nk_check_label(struct nk_context*, const char*, int active);
2926NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
2927NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
2928NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
2929NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
2930NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
2931NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
2932NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
2933/* =============================================================================
2934 *
2935 * RADIO BUTTON
2936 *
2937 * ============================================================================= */
2938NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
2939NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
2940NK_API int nk_option_label(struct nk_context*, const char*, int active);
2941NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
2942/* =============================================================================
2943 *
2944 * SELECTABLE
2945 *
2946 * ============================================================================= */
2947NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
2948NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
2949NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value);
2950NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
2951NK_API int nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int *value);
2952NK_API int nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int *value);
2953
2954NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
2955NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
2956NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
2957NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
2958NK_API int nk_select_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int value);
2959NK_API int nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int value);
2960
2961/* =============================================================================
2962 *
2963 * SLIDER
2964 *
2965 * ============================================================================= */
2966NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
2967NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
2968NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
2969NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
2970/* =============================================================================
2971 *
2972 * PROGRESSBAR
2973 *
2974 * ============================================================================= */
2975NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
2976NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
2977
2978/* =============================================================================
2979 *
2980 * COLOR PICKER
2981 *
2982 * ============================================================================= */
2985/* =============================================================================
2986 *
2987 * PROPERTIES
2988 *
2989 * =============================================================================
3060*/
3061/*/// #### nk_property_int
3080*/
3081NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
3082/*/// #### nk_property_float
3101*/
3102NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
3103/*/// #### nk_property_double
3122*/
3123NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
3124/*/// #### nk_propertyi
3145*/
3146NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
3147/*/// #### nk_propertyf
3168*/
3169NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
3170/*/// #### nk_propertyd
3191*/
3192NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
3193/* =============================================================================
3194 *
3195 * TEXT EDIT
3196 *
3197 * ============================================================================= */
3220 NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */
3221 NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */
3222 NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */
3223 NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
3224 NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */
3226NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
3231/* =============================================================================
3232 *
3233 * CHART
3234 *
3235 * ============================================================================= */
3236NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
3237NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
3238NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
3239NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value);
3243NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
3244NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset);
3245/* =============================================================================
3246 *
3247 * POPUP
3248 *
3249 * ============================================================================= */
3250NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
3253NK_API void nk_popup_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y);
3254NK_API void nk_popup_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y);
3255/* =============================================================================
3256 *
3257 * COMBOBOX
3258 *
3259 * ============================================================================= */
3260NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
3261NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size);
3262NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size);
3263NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size);
3264NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
3265NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size);
3266NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator,int *selected, int count, int item_height, struct nk_vec2 size);
3267NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size);
3268/* =============================================================================
3269 *
3270 * ABSTRACT COMBOBOX
3271 *
3272 * ============================================================================= */
3273NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
3274NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
3275NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
3277NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
3278NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
3279NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size);
3280NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
3281NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size);
3282NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
3283NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
3284NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3285NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
3286NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3287NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3290/* =============================================================================
3291 *
3292 * CONTEXTUAL
3293 *
3294 * ============================================================================= */
3295NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
3296NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
3297NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
3298NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3299NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3301NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3304/* =============================================================================
3305 *
3306 * TOOLTIP
3307 *
3308 * ============================================================================= */
3309NK_API void nk_tooltip(struct nk_context*, const char*);
3310#ifdef NK_INCLUDE_STANDARD_VARARGS
3311NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2);
3312NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
3313#endif
3314NK_API int nk_tooltip_begin(struct nk_context*, float width);
3316/* =============================================================================
3317 *
3318 * MENU
3319 *
3320 * ============================================================================= */
3323NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
3324NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
3325NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
3326NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
3327NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
3328NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
3329NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
3330NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
3331NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
3332NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
3333NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3334NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3335NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3336NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3339/* =============================================================================
3340 *
3341 * STYLE
3342 *
3343 * ============================================================================= */
3386NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
3394
3396NK_API int nk_style_push_float(struct nk_context*, float*, float);
3401
3408/* =============================================================================
3409 *
3410 * COLOR
3411 *
3412 * ============================================================================= */
3413NK_API struct nk_color nk_rgb(int r, int g, int b);
3414NK_API struct nk_color nk_rgb_iv(const int *rgb);
3416NK_API struct nk_color nk_rgb_f(float r, float g, float b);
3417NK_API struct nk_color nk_rgb_fv(const float *rgb);
3419NK_API struct nk_color nk_rgb_hex(const char *rgb);
3420
3421NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
3423NK_API struct nk_color nk_rgba_iv(const int *rgba);
3424NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
3425NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
3426NK_API struct nk_color nk_rgba_fv(const float *rgba);
3428NK_API struct nk_color nk_rgba_hex(const char *rgb);
3429
3430NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a);
3432NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in);
3433NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in);
3434
3435NK_API struct nk_color nk_hsv(int h, int s, int v);
3436NK_API struct nk_color nk_hsv_iv(const int *hsv);
3438NK_API struct nk_color nk_hsv_f(float h, float s, float v);
3439NK_API struct nk_color nk_hsv_fv(const float *hsv);
3440
3441NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
3442NK_API struct nk_color nk_hsva_iv(const int *hsva);
3443NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
3444NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
3445NK_API struct nk_color nk_hsva_fv(const float *hsva);
3446
3447/* color (conversion nuklear --> user) */
3448NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
3449NK_API void nk_color_fv(float *rgba_out, struct nk_color);
3451NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
3452NK_API void nk_color_dv(double *rgba_out, struct nk_color);
3453
3455NK_API void nk_color_hex_rgba(char *output, struct nk_color);
3456NK_API void nk_color_hex_rgb(char *output, struct nk_color);
3457
3458NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
3459NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
3460NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
3462NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
3463NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
3464
3465NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
3467NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
3468NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
3469NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
3470NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
3471/* =============================================================================
3472 *
3473 * IMAGE
3474 *
3475 * ============================================================================= */
3481NK_API int nk_image_is_subimage(const struct nk_image* img);
3482NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
3483NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
3484NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
3485/* =============================================================================
3486 *
3487 * MATH
3488 *
3489 * ============================================================================= */
3490NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
3491NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
3492
3493NK_API struct nk_vec2 nk_vec2(float x, float y);
3494NK_API struct nk_vec2 nk_vec2i(int x, int y);
3495NK_API struct nk_vec2 nk_vec2v(const float *xy);
3496NK_API struct nk_vec2 nk_vec2iv(const int *xy);
3497
3499NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
3500NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
3501NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
3502NK_API struct nk_rect nk_rectv(const float *xywh);
3503NK_API struct nk_rect nk_rectiv(const int *xywh);
3506/* =============================================================================
3507 *
3508 * STRING
3509 *
3510 * ============================================================================= */
3511NK_API int nk_strlen(const char *str);
3512NK_API int nk_stricmp(const char *s1, const char *s2);
3513NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
3514NK_API int nk_strtoi(const char *str, const char **endptr);
3515NK_API float nk_strtof(const char *str, const char **endptr);
3516NK_API double nk_strtod(const char *str, const char **endptr);
3517NK_API int nk_strfilter(const char *text, const char *regexp);
3518NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
3519NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
3520/* =============================================================================
3521 *
3522 * UTF-8
3523 *
3524 * ============================================================================= */
3525NK_API int nk_utf_decode(const char*, nk_rune*, int);
3527NK_API int nk_utf_len(const char*, int byte_len);
3528NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
3529/* ===============================================================
3530 *
3531 * FONT
3532 *
3533 * ===============================================================*/
3534/* Font handling in this library was designed to be quite customizable and lets
3535 you decide what you want to use and what you want to provide. There are three
3536 different ways to use the font atlas. The first two will use your font
3537 handling scheme and only requires essential data to run nuklear. The next
3538 slightly more advanced features is font handling with vertex buffer output.
3539 Finally the most complex API wise is using nuklear's font baking API.
3540
3541 1.) Using your own implementation without vertex buffer output
3542 --------------------------------------------------------------
3543 So first up the easiest way to do font handling is by just providing a
3544 `nk_user_font` struct which only requires the height in pixel of the used
3545 font and a callback to calculate the width of a string. This way of handling
3546 fonts is best fitted for using the normal draw shape command API where you
3547 do all the text drawing yourself and the library does not require any kind
3548 of deeper knowledge about which font handling mechanism you use.
3549 IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
3550 over the complete life time! I know this sucks but it is currently the only
3551 way to switch between fonts.
3552
3553 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
3554 {
3555 your_font_type *type = handle.ptr;
3556 float text_width = ...;
3557 return text_width;
3558 }
3559
3560 struct nk_user_font font;
3561 font.userdata.ptr = &your_font_class_or_struct;
3562 font.height = your_font_height;
3563 font.width = your_text_width_calculation;
3564
3565 struct nk_context ctx;
3566 nk_init_default(&ctx, &font);
3567
3568 2.) Using your own implementation with vertex buffer output
3569 --------------------------------------------------------------
3570 While the first approach works fine if you don't want to use the optional
3571 vertex buffer output it is not enough if you do. To get font handling working
3572 for these cases you have to provide two additional parameters inside the
3573 `nk_user_font`. First a texture atlas handle used to draw text as subimages
3574 of a bigger font atlas texture and a callback to query a character's glyph
3575 information (offset, size, ...). So it is still possible to provide your own
3576 font and use the vertex buffer output.
3577
3578 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
3579 {
3580 your_font_type *type = handle.ptr;
3581 float text_width = ...;
3582 return text_width;
3583 }
3584 void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
3585 {
3586 your_font_type *type = handle.ptr;
3587 glyph.width = ...;
3588 glyph.height = ...;
3589 glyph.xadvance = ...;
3590 glyph.uv[0].x = ...;
3591 glyph.uv[0].y = ...;
3592 glyph.uv[1].x = ...;
3593 glyph.uv[1].y = ...;
3594 glyph.offset.x = ...;
3595 glyph.offset.y = ...;
3596 }
3597
3598 struct nk_user_font font;
3599 font.userdata.ptr = &your_font_class_or_struct;
3600 font.height = your_font_height;
3601 font.width = your_text_width_calculation;
3602 font.query = query_your_font_glyph;
3603 font.texture.id = your_font_texture;
3604
3605 struct nk_context ctx;
3606 nk_init_default(&ctx, &font);
3607
3608 3.) Nuklear font baker
3609 ------------------------------------
3610 The final approach if you do not have a font handling functionality or don't
3611 want to use it in this library is by using the optional font baker.
3612 The font baker APIs can be used to create a font plus font atlas texture
3613 and can be used with or without the vertex buffer output.
3614
3615 It still uses the `nk_user_font` struct and the two different approaches
3616 previously stated still work. The font baker is not located inside
3617 `nk_context` like all other systems since it can be understood as more of
3618 an extension to nuklear and does not really depend on any `nk_context` state.
3619
3620 Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
3621 functions. If you don't care about memory just call the default version
3622 `nk_font_atlas_init_default` which will allocate all memory from the standard library.
3623 If you want to control memory allocation but you don't care if the allocated
3624 memory is temporary and therefore can be freed directly after the baking process
3625 is over or permanent you can call `nk_font_atlas_init`.
3626
3627 After successfully initializing the font baker you can add Truetype(.ttf) fonts from
3628 different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
3629 functions. Adding font will permanently store each font, font config and ttf memory block(!)
3630 inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
3631 the font baker by for example adding additional fonts you can call
3632 `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
3633
3634 As soon as you added all fonts you wanted you can now start the baking process
3635 for every selected glyph to image by calling `nk_font_atlas_bake`.
3636 The baking process returns image memory, width and height which can be used to
3637 either create your own image object or upload it to any graphics library.
3638 No matter which case you finally have to call `nk_font_atlas_end` which
3639 will free all temporary memory including the font atlas image so make sure
3640 you created our texture beforehand. `nk_font_atlas_end` requires a handle
3641 to your font texture or object and optionally fills a `struct nk_draw_null_texture`
3642 which can be used for the optional vertex output. If you don't want it just
3643 set the argument to `NULL`.
3644
3645 At this point you are done and if you don't want to reuse the font atlas you
3646 can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
3647 memory. Finally if you don't use the font atlas and any of it's fonts anymore
3648 you need to call `nk_font_atlas_clear` to free all memory still being used.
3649
3650 struct nk_font_atlas atlas;
3651 nk_font_atlas_init_default(&atlas);
3652 nk_font_atlas_begin(&atlas);
3653 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
3654 nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
3655 const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
3656 nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
3657
3658 struct nk_context ctx;
3659 nk_init_default(&ctx, &font->handle);
3660 while (1) {
3661
3662 }
3663 nk_font_atlas_clear(&atlas);
3664
3665 The font baker API is probably the most complex API inside this library and
3666 I would suggest reading some of my examples `example/` to get a grip on how
3667 to use the font atlas. There are a number of details I left out. For example
3668 how to merge fonts, configure a font with `nk_font_config` to use other languages,
3669 use another texture coordinate format and a lot more:
3670
3671 struct nk_font_config cfg = nk_font_config(font_pixel_height);
3672 cfg.merge_mode = nk_false or nk_true;
3673 cfg.range = nk_font_korean_glyph_ranges();
3674 cfg.coord_type = NK_COORD_PIXEL;
3675 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
3676
3677*/
3678struct nk_user_font_glyph;
3679typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
3680typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
3681 struct nk_user_font_glyph *glyph,
3682 nk_rune codepoint, nk_rune next_codepoint);
3683
3684#if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT)
3685struct nk_user_font_glyph {
3686 struct nk_vec2 uv[2];
3687 /* texture coordinates */
3688 struct nk_vec2 offset;
3689 /* offset between top left and glyph */
3690 float width, height;
3691 /* size of the glyph */
3692 float xadvance;
3693 /* offset to the next glyph */
3694};
3695#endif
3696
3699 /* user provided font handle */
3700 float height;
3701 /* max height of the font */
3703 /* font string width in pixel callback */
3704#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3706 /* font glyph callback to query drawing info */
3707 nk_handle texture;
3708 /* texture handle to the used font atlas or texture */
3709#endif
3710};
3711
3712#ifdef NK_INCLUDE_FONT_BAKING
3713enum nk_font_coord_type {
3714 NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
3715 NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
3716};
3717
3718struct nk_font;
3719struct nk_baked_font {
3720 float height;
3721 /* height of the font */
3722 float ascent, descent;
3723 /* font glyphs ascent and descent */
3724 nk_rune glyph_offset;
3725 /* glyph array offset inside the font glyph baking output array */
3726 nk_rune glyph_count;
3727 /* number of glyphs of this font inside the glyph baking array output */
3728 const nk_rune *ranges;
3729 /* font codepoint ranges as pairs of (from/to) and 0 as last element */
3730};
3731
3732struct nk_font_config {
3733 struct nk_font_config *next;
3734 /* NOTE: only used internally */
3735 void *ttf_blob;
3736 /* pointer to loaded TTF file memory block.
3737 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
3738 nk_size ttf_size;
3739 /* size of the loaded TTF file memory block
3740 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
3741
3742 unsigned char ttf_data_owned_by_atlas;
3743 /* used inside font atlas: default to: 0*/
3744 unsigned char merge_mode;
3745 /* merges this font into the last font */
3746 unsigned char pixel_snap;
3747 /* align every character to pixel boundary (if true set oversample (1,1)) */
3748 unsigned char oversample_v, oversample_h;
3749 /* rasterize at hight quality for sub-pixel position */
3750 unsigned char padding[3];
3751
3752 float size;
3753 /* baked pixel height of the font */
3754 enum nk_font_coord_type coord_type;
3755 /* texture coordinate format with either pixel or UV coordinates */
3756 struct nk_vec2 spacing;
3757 /* extra pixel spacing between glyphs */
3758 const nk_rune *range;
3759 /* list of unicode ranges (2 values per range, zero terminated) */
3760 struct nk_baked_font *font;
3761 /* font to setup in the baking process: NOTE: not needed for font atlas */
3762 nk_rune fallback_glyph;
3763 /* fallback glyph to use if a given rune is not found */
3764 struct nk_font_config *n;
3765 struct nk_font_config *p;
3766};
3767
3768struct nk_font_glyph {
3769 nk_rune codepoint;
3770 float xadvance;
3771 float x0, y0, x1, y1, w, h;
3772 float u0, v0, u1, v1;
3773};
3774
3775struct nk_font {
3776 struct nk_font *next;
3777 struct nk_user_font handle;
3778 struct nk_baked_font info;
3779 float scale;
3780 struct nk_font_glyph *glyphs;
3781 const struct nk_font_glyph *fallback;
3782 nk_rune fallback_codepoint;
3783 nk_handle texture;
3784 struct nk_font_config *config;
3785};
3786
3787enum nk_font_atlas_format {
3788 NK_FONT_ATLAS_ALPHA8,
3789 NK_FONT_ATLAS_RGBA32
3790};
3791
3792struct nk_font_atlas {
3793 void *pixel;
3794 int tex_width;
3795 int tex_height;
3796
3797 struct nk_allocator permanent;
3798 struct nk_allocator temporary;
3799
3800 struct nk_recti custom;
3801 struct nk_cursor cursors[NK_CURSOR_COUNT];
3802
3803 int glyph_count;
3804 struct nk_font_glyph *glyphs;
3805 struct nk_font *default_font;
3806 struct nk_font *fonts;
3807 struct nk_font_config *config;
3808 int font_num;
3809};
3810
3811/* some language glyph codepoint ranges */
3812NK_API const nk_rune *nk_font_default_glyph_ranges(void);
3813NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
3814NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
3815NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
3816
3817#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
3818NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
3819#endif
3820NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
3821NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
3822NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
3823NK_API struct nk_font_config nk_font_config(float pixel_height);
3824NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
3825#ifdef NK_INCLUDE_DEFAULT_FONT
3826NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
3827#endif
3828NK_API struct nk_font* nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, nk_size size, float height, const struct nk_font_config *config);
3829#ifdef NK_INCLUDE_STANDARD_IO
3830NK_API struct nk_font* nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, float height, const struct nk_font_config*);
3831#endif
3832NK_API struct nk_font *nk_font_atlas_add_compressed(struct nk_font_atlas*, void *memory, nk_size size, float height, const struct nk_font_config*);
3833NK_API struct nk_font* nk_font_atlas_add_compressed_base85(struct nk_font_atlas*, const char *data, float height, const struct nk_font_config *config);
3834NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
3835NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
3836NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
3837NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
3838NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
3839
3840#endif
3841
3842/* ==============================================================
3843 *
3844 * MEMORY BUFFER
3845 *
3846 * ===============================================================*/
3847/* A basic (double)-buffer with linear allocation and resetting as only
3848 freeing policy. The buffer's main purpose is to control all memory management
3849 inside the GUI toolkit and still leave memory control as much as possible in
3850 the hand of the user while also making sure the library is easy to use if
3851 not as much control is needed.
3852 In general all memory inside this library can be provided from the user in
3853 three different ways.
3854
3855 The first way and the one providing most control is by just passing a fixed
3856 size memory block. In this case all control lies in the hand of the user
3857 since he can exactly control where the memory comes from and how much memory
3858 the library should consume. Of course using the fixed size API removes the
3859 ability to automatically resize a buffer if not enough memory is provided so
3860 you have to take over the resizing. While being a fixed sized buffer sounds
3861 quite limiting, it is very effective in this library since the actual memory
3862 consumption is quite stable and has a fixed upper bound for a lot of cases.
3863
3864 If you don't want to think about how much memory the library should allocate
3865 at all time or have a very dynamic UI with unpredictable memory consumption
3866 habits but still want control over memory allocation you can use the dynamic
3867 allocator based API. The allocator consists of two callbacks for allocating
3868 and freeing memory and optional userdata so you can plugin your own allocator.
3869
3870 The final and easiest way can be used by defining
3871 NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
3872 allocation functions malloc and free and takes over complete control over
3873 memory in this library.
3874*/
3876 void *memory;
3877 unsigned int type;
3882};
3883
3888
3894
3898};
3899
3900struct nk_memory {void *ptr;nk_size size;};
3903 /* buffer marker to free a buffer to a certain offset */
3905 /* allocator callback for dynamic buffers */
3907 /* memory management type */
3909 /* memory and size of the current memory block */
3911 /* growing factor for dynamic memory management */
3913 /* total amount of memory allocated */
3915 /* totally consumed memory given that enough memory is present */
3917 /* number of allocation calls */
3919 /* current size of the buffer */
3920};
3921
3922#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
3923NK_API void nk_buffer_init_default(struct nk_buffer*);
3924#endif
3926NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
3928NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
3934NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
3936
3937/* ==============================================================
3938 *
3939 * STRING
3940 *
3941 * ===============================================================*/
3942/* Basic string buffer which is only used in context with the text editor
3943 * to manage and manipulate dynamic or fixed size string content. This is _NOT_
3944 * the default string handling method. The only instance you should have any contact
3945 * with this API is if you interact with an `nk_text_edit` object inside one of the
3946 * copy and paste functions and even there only for more advanced cases. */
3947struct nk_str {
3949 int len; /* in codepoints/runes/glyphs */
3950};
3951
3952#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
3953NK_API void nk_str_init_default(struct nk_str*);
3954#endif
3955NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
3959
3960NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
3961NK_API int nk_str_append_str_char(struct nk_str*, const char*);
3962NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
3963NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
3966
3967NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
3968NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
3969
3970NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
3971NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
3972NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
3973NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
3974NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
3975NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
3976
3977NK_API void nk_str_remove_chars(struct nk_str*, int len);
3978NK_API void nk_str_remove_runes(struct nk_str *str, int len);
3979NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
3980NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
3981
3982NK_API char *nk_str_at_char(struct nk_str*, int pos);
3983NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
3984NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
3985NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
3986NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
3987
3988NK_API char *nk_str_get(struct nk_str*);
3989NK_API const char *nk_str_get_const(const struct nk_str*);
3992
3993/*===============================================================
3994 *
3995 * TEXT EDITOR
3996 *
3997 * ===============================================================*/
3998/* Editing text in this library is handled by either `nk_edit_string` or
3999 * `nk_edit_buffer`. But like almost everything in this library there are multiple
4000 * ways of doing it and a balance between control and ease of use with memory
4001 * as well as functionality controlled by flags.
4002 *
4003 * This library generally allows three different levels of memory control:
4004 * First of is the most basic way of just providing a simple char array with
4005 * string length. This method is probably the easiest way of handling simple
4006 * user text input. Main upside is complete control over memory while the biggest
4007 * downside in comparison with the other two approaches is missing undo/redo.
4008 *
4009 * For UIs that require undo/redo the second way was created. It is based on
4010 * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
4011 * This is mainly useful if you want something more like a text editor but don't want
4012 * to have a dynamically growing buffer.
4013 *
4014 * The final way is using a dynamically growing nk_text_edit struct, which
4015 * has both a default version if you don't care where memory comes from and an
4016 * allocator version if you do. While the text editor is quite powerful for its
4017 * complexity I would not recommend editing gigabytes of data with it.
4018 * It is rather designed for uses cases which make sense for a GUI library not for
4019 * an full blown text editor.
4020 */
4021#ifndef NK_TEXTEDIT_UNDOSTATECOUNT
4022#define NK_TEXTEDIT_UNDOSTATECOUNT 99
4023#endif
4024
4025#ifndef NK_TEXTEDIT_UNDOCHARCOUNT
4026#define NK_TEXTEDIT_UNDOCHARCOUNT 999
4027#endif
4028
4029struct nk_text_edit;
4034};
4035
4041};
4042
4050};
4051
4056
4062
4068
4072 unsigned char mode;
4074 unsigned char initialized;
4075 unsigned char has_preferred_x;
4076 unsigned char single_line;
4077 unsigned char active;
4078 unsigned char padding1;
4081};
4082
4083/* filter function */
4084NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
4085NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
4086NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
4087NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
4088NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
4089NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
4090NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
4091
4092/* text editor */
4093#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4094NK_API void nk_textedit_init_default(struct nk_text_edit*);
4095#endif
4097NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
4099NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
4100NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
4104NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
4107
4108/* ===============================================================
4109 *
4110 * DRAWING
4111 *
4112 * ===============================================================*/
4113/* This library was designed to be render backend agnostic so it does
4114 not draw anything to screen. Instead all drawn shapes, widgets
4115 are made of, are buffered into memory and make up a command queue.
4116 Each frame therefore fills the command buffer with draw commands
4117 that then need to be executed by the user and his own render backend.
4118 After that the command buffer needs to be cleared and a new frame can be
4119 started. It is probably important to note that the command buffer is the main
4120 drawing API and the optional vertex buffer API only takes this format and
4121 converts it into a hardware accessible format.
4122
4123 To use the command queue to draw your own widgets you can access the
4124 command buffer of each window by calling `nk_window_get_canvas` after
4125 previously having called `nk_begin`:
4126
4127 void draw_red_rectangle_widget(struct nk_context *ctx)
4128 {
4129 struct nk_command_buffer *canvas;
4130 struct nk_input *input = &ctx->input;
4131 canvas = nk_window_get_canvas(ctx);
4132
4133 struct nk_rect space;
4134 enum nk_widget_layout_states state;
4135 state = nk_widget(&space, ctx);
4136 if (!state) return;
4137
4138 if (state != NK_WIDGET_ROM)
4139 update_your_widget_by_user_input(...);
4140 nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
4141 }
4142
4143 if (nk_begin(...)) {
4144 nk_layout_row_dynamic(ctx, 25, 1);
4145 draw_red_rectangle_widget(ctx);
4146 }
4147 nk_end(..)
4148
4149 Important to know if you want to create your own widgets is the `nk_widget`
4150 call. It allocates space on the panel reserved for this widget to be used,
4151 but also returns the state of the widget space. If your widget is not seen and does
4152 not have to be updated it is '0' and you can just return. If it only has
4153 to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
4154 update and draw your widget. The reason for separating is to only draw and
4155 update what is actually necessary which is crucial for performance.
4156*/
4178
4179/* command base and header of every command inside the buffer */
4183#ifdef NK_INCLUDE_COMMAND_USERDATA
4184 nk_handle userdata;
4185#endif
4186};
4187
4190 short x, y;
4191 unsigned short w, h;
4192};
4193
4196 unsigned short line_thickness;
4200};
4201
4204 unsigned short line_thickness;
4207 struct nk_vec2i ctrl[2];
4209};
4210
4213 unsigned short rounding;
4214 unsigned short line_thickness;
4215 short x, y;
4216 unsigned short w, h;
4218};
4219
4222 unsigned short rounding;
4223 short x, y;
4224 unsigned short w, h;
4226};
4227
4230 short x, y;
4231 unsigned short w, h;
4236};
4237
4240 unsigned short line_thickness;
4241 struct nk_vec2i a;
4242 struct nk_vec2i b;
4243 struct nk_vec2i c;
4245};
4246
4249 struct nk_vec2i a;
4250 struct nk_vec2i b;
4251 struct nk_vec2i c;
4253};
4254
4257 short x, y;
4258 unsigned short line_thickness;
4259 unsigned short w, h;
4261};
4262
4265 short x, y;
4266 unsigned short w, h;
4268};
4269
4272 short cx, cy;
4273 unsigned short r;
4274 unsigned short line_thickness;
4275 float a[2];
4277};
4278
4281 short cx, cy;
4282 unsigned short r;
4283 float a[2];
4285};
4286
4290 unsigned short line_thickness;
4291 unsigned short point_count;
4292 struct nk_vec2i points[1];
4293};
4294
4298 unsigned short point_count;
4299 struct nk_vec2i points[1];
4300};
4301
4305 unsigned short line_thickness;
4306 unsigned short point_count;
4307 struct nk_vec2i points[1];
4308};
4309
4312 short x, y;
4313 unsigned short w, h;
4316};
4317
4318typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
4319 unsigned short w, unsigned short h, nk_handle callback_data);
4322 short x, y;
4323 unsigned short w, h;
4326};
4327
4330 const struct nk_user_font *font;
4333 short x, y;
4334 unsigned short w, h;
4335 float height;
4337 char string[1];
4338};
4339
4344
4351};
4352
4353/* shape outlines */
4354NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color);
4355NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
4356NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
4357NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
4358NK_API void nk_stroke_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color);
4359NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
4360NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
4361NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
4362
4363/* filled shades */
4364NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
4365NK_API void nk_fill_rect_multi_color(struct nk_command_buffer*, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
4367NK_API void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color);
4368NK_API void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color);
4369NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
4370
4371/* misc */
4372NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
4373NK_API void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color);
4376
4377/* ===============================================================
4378 *
4379 * INPUT
4380 *
4381 * ===============================================================*/
4383 int down;
4384 unsigned int clicked;
4386};
4387struct nk_mouse {
4389 struct nk_vec2 pos;
4393 unsigned char grab;
4394 unsigned char grabbed;
4395 unsigned char ungrab;
4396};
4397
4398struct nk_key {
4399 int down;
4400 unsigned int clicked;
4401};
4406};
4407
4408struct nk_input {
4411};
4412
4417NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down);
4428
4429/* ===============================================================
4430 *
4431 * DRAW LIST
4432 *
4433 * ===============================================================*/
4434#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4435/* The optional vertex buffer draw list provides a 2D drawing context
4436 with antialiasing functionality which takes basic filled or outlined shapes
4437 or a path and outputs vertexes, elements and draw commands.
4438 The actual draw list API is not required to be used directly while using this
4439 library since converting the default library draw command output is done by
4440 just calling `nk_convert` but I decided to still make this library accessible
4441 since it can be useful.
4442
4443 The draw list is based on a path buffering and polygon and polyline
4444 rendering API which allows a lot of ways to draw 2D content to screen.
4445 In fact it is probably more powerful than needed but allows even more crazy
4446 things than this library provides by default.
4447*/
4448#ifdef NK_UINT_DRAW_INDEX
4449typedef nk_uint nk_draw_index;
4450#else
4451typedef nk_ushort nk_draw_index;
4452#endif
4453enum nk_draw_list_stroke {
4454 NK_STROKE_OPEN = nk_false,
4455 /* build up path has no connection back to the beginning */
4456 NK_STROKE_CLOSED = nk_true
4457 /* build up path has a connection back to the beginning */
4458};
4459
4460enum nk_draw_vertex_layout_attribute {
4461 NK_VERTEX_POSITION,
4462 NK_VERTEX_COLOR,
4463 NK_VERTEX_TEXCOORD,
4464 NK_VERTEX_ATTRIBUTE_COUNT
4465};
4466
4467enum nk_draw_vertex_layout_format {
4468 NK_FORMAT_SCHAR,
4469 NK_FORMAT_SSHORT,
4470 NK_FORMAT_SINT,
4471 NK_FORMAT_UCHAR,
4472 NK_FORMAT_USHORT,
4473 NK_FORMAT_UINT,
4474 NK_FORMAT_FLOAT,
4475 NK_FORMAT_DOUBLE,
4476
4477NK_FORMAT_COLOR_BEGIN,
4478 NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
4479 NK_FORMAT_R16G15B16,
4480 NK_FORMAT_R32G32B32,
4481
4482 NK_FORMAT_R8G8B8A8,
4483 NK_FORMAT_B8G8R8A8,
4484 NK_FORMAT_R16G15B16A16,
4485 NK_FORMAT_R32G32B32A32,
4486 NK_FORMAT_R32G32B32A32_FLOAT,
4487 NK_FORMAT_R32G32B32A32_DOUBLE,
4488
4489 NK_FORMAT_RGB32,
4490 NK_FORMAT_RGBA32,
4491NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
4492 NK_FORMAT_COUNT
4493};
4494
4495#define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
4496struct nk_draw_vertex_layout_element {
4497 enum nk_draw_vertex_layout_attribute attribute;
4498 enum nk_draw_vertex_layout_format format;
4499 nk_size offset;
4500};
4501
4502struct nk_draw_command {
4503 unsigned int elem_count;
4504 /* number of elements in the current draw batch */
4505 struct nk_rect clip_rect;
4506 /* current screen clipping rectangle */
4507 nk_handle texture;
4508 /* current texture to set */
4509#ifdef NK_INCLUDE_COMMAND_USERDATA
4510 nk_handle userdata;
4511#endif
4512};
4513
4514struct nk_draw_list {
4515 struct nk_rect clip_rect;
4516 struct nk_vec2 circle_vtx[12];
4517 struct nk_convert_config config;
4518
4519 struct nk_buffer *buffer;
4520 struct nk_buffer *vertices;
4521 struct nk_buffer *elements;
4522
4523 unsigned int element_count;
4524 unsigned int vertex_count;
4525 unsigned int cmd_count;
4526 nk_size cmd_offset;
4527
4528 unsigned int path_count;
4529 unsigned int path_offset;
4530
4531 enum nk_anti_aliasing line_AA;
4532 enum nk_anti_aliasing shape_AA;
4533
4534#ifdef NK_INCLUDE_COMMAND_USERDATA
4535 nk_handle userdata;
4536#endif
4537};
4538
4539/* draw list */
4540NK_API void nk_draw_list_init(struct nk_draw_list*);
4541NK_API void nk_draw_list_setup(struct nk_draw_list*, const struct nk_convert_config*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, enum nk_anti_aliasing line_aa,enum nk_anti_aliasing shape_aa);
4542
4543/* drawing */
4544#define nk_draw_list_foreach(cmd, can, b) for((cmd)=nk__draw_list_begin(can, b); (cmd)!=0; (cmd)=nk__draw_list_next(cmd, b, can))
4545NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
4546NK_API const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*);
4547NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
4548
4549/* path */
4550NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
4551NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
4552NK_API void nk_draw_list_path_arc_to_fast(struct nk_draw_list*, struct nk_vec2 center, float radius, int a_min, int a_max);
4553NK_API void nk_draw_list_path_arc_to(struct nk_draw_list*, struct nk_vec2 center, float radius, float a_min, float a_max, unsigned int segments);
4554NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
4555NK_API void nk_draw_list_path_curve_to(struct nk_draw_list*, struct nk_vec2 p2, struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments);
4556NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
4557NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
4558
4559/* stroke */
4560NK_API void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness);
4561NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
4562NK_API void nk_draw_list_stroke_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color, float thickness);
4563NK_API void nk_draw_list_stroke_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color, unsigned int segs, float thickness);
4564NK_API void nk_draw_list_stroke_curve(struct nk_draw_list*, struct nk_vec2 p0, struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, struct nk_color, unsigned int segments, float thickness);
4565NK_API void nk_draw_list_stroke_poly_line(struct nk_draw_list*, const struct nk_vec2 *pnts, const unsigned int cnt, struct nk_color, enum nk_draw_list_stroke, float thickness, enum nk_anti_aliasing);
4566
4567/* fill */
4568NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
4569NK_API void nk_draw_list_fill_rect_multi_color(struct nk_draw_list*, struct nk_rect rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
4570NK_API void nk_draw_list_fill_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color);
4571NK_API void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs);
4572NK_API void nk_draw_list_fill_poly_convex(struct nk_draw_list*, const struct nk_vec2 *points, const unsigned int count, struct nk_color, enum nk_anti_aliasing);
4573
4574/* misc */
4575NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
4576NK_API void nk_draw_list_add_text(struct nk_draw_list*, const struct nk_user_font*, struct nk_rect, const char *text, int len, float font_height, struct nk_color);
4577#ifdef NK_INCLUDE_COMMAND_USERDATA
4578NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
4579#endif
4580
4581#endif
4582
4583/* ===============================================================
4584 *
4585 * GUI
4586 *
4587 * ===============================================================*/
4592
4596};
4597
4601};
4602
4606};
4607
4609 /* background */
4614
4615 /* text */
4621
4622 /* properties */
4623 float border;
4628
4629 /* optional user callbacks */
4633};
4634
4636 /* background */
4641
4642 /* cursor */
4645
4646 /* text */
4652
4653 /* properties */
4656 float spacing;
4657 float border;
4658
4659 /* optional user callbacks */
4663};
4664
4666 /* background (inactive) */
4670
4671 /* background (active) */
4675
4676 /* text color (inactive) */
4680
4681 /* text color (active) */
4687
4688 /* properties */
4693
4694 /* optional user callbacks */
4698};
4699
4701 /* background */
4706
4707 /* background bar */
4712
4713 /* cursor */
4717
4718 /* properties */
4719 float border;
4725
4726 /* optional buttons */
4732
4733 /* optional user callbacks */
4737};
4738
4740 /* background */
4745
4746 /* cursor */
4751
4752 /* properties */
4754 float border;
4758
4759 /* optional user callbacks */
4763};
4764
4766 /* background */
4771
4772 /* cursor */
4777
4778 /* properties */
4779 float border;
4784
4785 /* optional buttons */
4791
4792 /* optional user callbacks */
4796};
4797
4799 /* background */
4805
4806 /* cursor */
4811
4812 /* text (unselected) */
4816
4817 /* text (selected) */
4822
4823 /* properties */
4824 float border;
4830};
4831
4833 /* background */
4838
4839 /* text */
4843
4844 /* symbols */
4847
4848 /* properties */
4849 float border;
4852
4856
4857 /* optional user callbacks */
4861};
4862
4864 /* colors */
4869
4870 /* properties */
4871 float border;
4874};
4875
4877 /* background */
4882
4883 /* label */
4887
4888 /* symbol */
4892
4893 /* button */
4898
4899 /* properties */
4900 float border;
4905};
4906
4908 /* background */
4912
4913 /* button */
4920
4921 /* properties */
4922 float border;
4924 float indent;
4927};
4928
4934 /* background */
4938
4939 /* button */
4945
4946 /* title */
4950
4951 /* properties */
4956};
4957
4962
4971
4972 float border;
4980
4985
4993};
4994
4995struct nk_style {
4996 const struct nk_user_font *font;
5001
5019};
5020
5024
5025/*==============================================================
5026 * PANEL
5027 * =============================================================*/
5028#ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
5029#define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
5030#endif
5031#ifndef NK_CHART_MAX_SLOT
5032#define NK_CHART_MAX_SLOT 4
5033#endif
5034
5050
5055 float min, max, range;
5059};
5060
5061struct nk_chart {
5062 int slot;
5063 float x, y, w, h;
5065};
5066
5082 float height;
5085 const float *ratio;
5089 float filled;
5093};
5094
5101};
5102
5104 float x, y, w, h;
5106};
5107
5108struct nk_panel {
5114 float at_x, at_y, max_x;
5117 float border;
5118 unsigned int has_scrolling;
5125};
5126
5127/*==============================================================
5128 * WINDOW
5129 * =============================================================*/
5130#ifndef NK_WINDOW_MAX_NAME
5131#define NK_WINDOW_MAX_NAME 64
5132#endif
5133
5134struct nk_table;
5138 /* special window type growing up in height while being filled to a certain maximum height */
5140 /* sets window widgets into a read only mode and does not allow input changes */
5142 /* prevents all interaction caused by input to either window or widgets inside */
5144 /* Hides window and stops any window interaction and drawing */
5146 /* Directly closes and frees the window at the end of the frame */
5148 /* marks the window as minimized */
5150 /* Removes read only mode at the end of the window */
5152
5159 unsigned combo_count;
5161 unsigned active_con;
5163};
5164
5167 unsigned int seq;
5168 unsigned int old;
5174 unsigned char mode;
5175 unsigned char single_line;
5176};
5177
5186 unsigned int seq;
5187 unsigned int old;
5189};
5190
5192 unsigned int seq;
5196
5202
5203 /* persistent widget state */
5207 unsigned int scrolled;
5208
5210 unsigned int table_count;
5211
5212 /* window list hooks */
5216};
5217
5218/*==============================================================
5219 * STACK
5220 * =============================================================*/
5221/* The style modifier stack can be used to temporarily change a
5222 * property inside `nk_style`. For example if you want a special
5223 * red button you can temporarily push the old button color onto a stack
5224 * draw the button with a red color and then you just pop the old color
5225 * back from the stack:
5226 *
5227 * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
5228 * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
5229 * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
5230 * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
5231 *
5232 * nk_button(...);
5233 *
5234 * nk_style_pop_style_item(ctx);
5235 * nk_style_pop_style_item(ctx);
5236 * nk_style_pop_style_item(ctx);
5237 * nk_style_pop_vec2(ctx);
5238 *
5239 * Nuklear has a stack for style_items, float properties, vector properties,
5240 * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
5241 * which can be changed at compile time.
5242 */
5243#ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
5244#define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
5245#endif
5246
5247#ifndef NK_FONT_STACK_SIZE
5248#define NK_FONT_STACK_SIZE 8
5249#endif
5250
5251#ifndef NK_STYLE_ITEM_STACK_SIZE
5252#define NK_STYLE_ITEM_STACK_SIZE 16
5253#endif
5254
5255#ifndef NK_FLOAT_STACK_SIZE
5256#define NK_FLOAT_STACK_SIZE 32
5257#endif
5258
5259#ifndef NK_VECTOR_STACK_SIZE
5260#define NK_VECTOR_STACK_SIZE 16
5261#endif
5262
5263#ifndef NK_FLAGS_STACK_SIZE
5264#define NK_FLAGS_STACK_SIZE 32
5265#endif
5266
5267#ifndef NK_COLOR_STACK_SIZE
5268#define NK_COLOR_STACK_SIZE 32
5269#endif
5270
5271#define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
5272 struct nk_config_stack_##name##_element {\
5273 prefix##_##type *address;\
5274 prefix##_##type old_value;\
5275 }
5276#define NK_CONFIG_STACK(type,size)\
5277 struct nk_config_stack_##type {\
5278 int head;\
5279 struct nk_config_stack_##type##_element elements[size];\
5280 }
5281
5282#define nk_float float
5283NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
5285NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
5287NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
5288NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
5289NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
5290
5298
5300 struct nk_config_stack_style_item style_items;
5301 struct nk_config_stack_float floats;
5302 struct nk_config_stack_vec2 vectors;
5303 struct nk_config_stack_flags flags;
5304 struct nk_config_stack_color colors;
5305 struct nk_config_stack_user_font fonts;
5306 struct nk_config_stack_button_behavior button_behaviors;
5307};
5308
5309/*==============================================================
5310 * CONTEXT
5311 * =============================================================*/
5312#define NK_VALUE_PAGE_CAPACITY \
5313 (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
5314
5315struct nk_table {
5316 unsigned int seq;
5317 unsigned int size;
5320 struct nk_table *next, *prev;
5321};
5322
5327};
5328
5333};
5334
5335struct nk_page {
5336 unsigned int size;
5337 struct nk_page *next;
5339};
5340
5341struct nk_pool {
5344 unsigned int page_count;
5347 unsigned capacity;
5350};
5351
5353/* public: can be accessed freely */
5362
5363/* private:
5364 should only be accessed if you
5365 know what you are doing */
5366#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
5367 struct nk_draw_list draw_list;
5368#endif
5369#ifdef NK_INCLUDE_COMMAND_USERDATA
5370 nk_handle userdata;
5371#endif
5372 /* text editor objects are quite big because of an internal
5373 * undo/redo stack. Therefore it does not make sense to have one for
5374 * each window for temporary use cases, so I only provide *one* instance
5375 * for all windows. This works because the content is cleared anyway */
5377 /* draw buffer used for overlay drawing operation like cursor */
5379
5380 /* windows */
5389 unsigned int count;
5390 unsigned int seq;
5391};
5392
5393/* ==============================================================
5394 * MATH
5395 * =============================================================== */
5396#define NK_PI 3.141592654f
5397#define NK_UTF_INVALID 0xFFFD
5398#define NK_MAX_FLOAT_PRECISION 2
5399
5400#define NK_UNUSED(x) ((void)(x))
5401#define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
5402#define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
5403#define NK_ABS(a) (((a) < 0) ? -(a) : (a))
5404#define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
5405#define NK_INBOX(px, py, x, y, w, h)\
5406 (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
5407#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
5408 (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
5409#define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
5410 (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
5411
5412#define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
5413#define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
5414#define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
5415#define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
5416
5417#define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
5418#define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
5419#define nk_zero_struct(s) nk_zero(&s, sizeof(s))
5420
5421/* ==============================================================
5422 * ALIGNMENT
5423 * =============================================================== */
5424/* Pointer to Integer type conversion for pointer alignment */
5425#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
5426# define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
5427# define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
5428#elif !defined(__GNUC__) /* works for compilers other than LLVM */
5429# define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
5430# define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
5431#elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
5432# define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
5433# define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
5434#else /* generates warning but works */
5435# define NK_UINT_TO_PTR(x) ((void*)(x))
5436# define NK_PTR_TO_UINT(x) ((nk_size)(x))
5437#endif
5438
5439#define NK_ALIGN_PTR(x, mask)\
5440 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
5441#define NK_ALIGN_PTR_BACK(x, mask)\
5442 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
5443
5444#define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
5445#define NK_CONTAINER_OF(ptr,type,member)\
5446 (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
5447
5448#ifdef __cplusplus
5449}
5450#endif
5451
5452#ifdef __cplusplus
5453template<typename T> struct nk_alignof;
5454template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
5455template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
5456template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
5457 diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
5458#define NK_ALIGNOF(t) (nk_alignof<t>::value)
5459#elif defined(_MSC_VER)
5460#define NK_ALIGNOF(t) (__alignof(t))
5461#else
5462#define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
5463#endif
5464
5465#endif /* NK_NUKLEAR_H_ */
5466#endif /* NK_SINGLE_HEADER */
5467
5468#ifdef NK_IMPLEMENTATION
5469#ifndef NK_INTERNAL_H
5470#define NK_INTERNAL_H
5471
5472#ifndef NK_POOL_DEFAULT_CAPACITY
5473#define NK_POOL_DEFAULT_CAPACITY 16
5474#endif
5475
5476#ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
5477#define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
5478#endif
5479
5480#ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
5481#define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
5482#endif
5483
5484/* standard library headers */
5485#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
5486#include <stdlib.h> /* malloc, free */
5487#endif
5488#ifdef NK_INCLUDE_STANDARD_IO
5489#include <stdio.h> /* fopen, fclose,... */
5490#endif
5491#ifdef NK_INCLUDE_STANDARD_VARARGS
5492#include <stdarg.h> /* valist, va_start, va_end, ... */
5493#endif
5494#ifndef NK_ASSERT
5495#include <assert.h>
5496#define NK_ASSERT(expr) assert(expr)
5497#endif
5498
5499#ifndef NK_MEMSET
5500#define NK_MEMSET nk_memset
5501#endif
5502#ifndef NK_MEMCPY
5503#define NK_MEMCPY nk_memcopy
5504#endif
5505#ifndef NK_SQRT
5506#define NK_SQRT nk_sqrt
5507#endif
5508#ifndef NK_SIN
5509#define NK_SIN nk_sin
5510#endif
5511#ifndef NK_COS
5512#define NK_COS nk_cos
5513#endif
5514#ifndef NK_STRTOD
5515#define NK_STRTOD nk_strtod
5516#endif
5517#ifndef NK_DTOA
5518#define NK_DTOA nk_dtoa
5519#endif
5520
5521#define NK_DEFAULT (-1)
5522
5523#ifndef NK_VSNPRINTF
5524/* If your compiler does support `vsnprintf` I would highly recommend
5525 * defining this to vsnprintf instead since `vsprintf` is basically
5526 * unbelievable unsafe and should *NEVER* be used. But I have to support
5527 * it since C89 only provides this unsafe version. */
5528 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
5529 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
5530 (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
5531 (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
5532 defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
5533 #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
5534 #else
5535 #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
5536 #endif
5537#endif
5538
5539#define NK_SCHAR_MIN (-127)
5540#define NK_SCHAR_MAX 127
5541#define NK_UCHAR_MIN 0
5542#define NK_UCHAR_MAX 256
5543#define NK_SSHORT_MIN (-32767)
5544#define NK_SSHORT_MAX 32767
5545#define NK_USHORT_MIN 0
5546#define NK_USHORT_MAX 65535
5547#define NK_SINT_MIN (-2147483647)
5548#define NK_SINT_MAX 2147483647
5549#define NK_UINT_MIN 0
5550#define NK_UINT_MAX 4294967295u
5551
5552/* Make sure correct type size:
5553 * This will fire with a negative subscript error if the type sizes
5554 * are set incorrectly by the compiler, and compile out if not */
5555NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
5556NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
5557NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
5558NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
5559NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
5560NK_STATIC_ASSERT(sizeof(nk_short) == 2);
5561NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
5562NK_STATIC_ASSERT(sizeof(nk_int) == 4);
5563NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
5564
5565NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
5566#define NK_FLOAT_PRECISION 0.00000000000001
5567
5568NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
5569NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
5570NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
5571NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
5572NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
5573NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
5574
5575/* widget */
5576#define nk_widget_state_reset(s)\
5577 if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
5578 (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
5579 else (*(s)) = NK_WIDGET_STATE_INACTIVE;
5580
5581/* math */
5582NK_LIB float nk_inv_sqrt(float n);
5583NK_LIB float nk_sqrt(float x);
5584NK_LIB float nk_sin(float x);
5585NK_LIB float nk_cos(float x);
5586NK_LIB nk_uint nk_round_up_pow2(nk_uint v);
5587NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount);
5588NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad);
5589NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1);
5590NK_LIB double nk_pow(double x, int n);
5591NK_LIB int nk_ifloord(double x);
5592NK_LIB int nk_ifloorf(float x);
5593NK_LIB int nk_iceilf(float x);
5594NK_LIB int nk_log10(double n);
5595
5596/* util */
5597enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
5598NK_LIB int nk_is_lower(int c);
5599NK_LIB int nk_is_upper(int c);
5600NK_LIB int nk_to_upper(int c);
5601NK_LIB int nk_to_lower(int c);
5602NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n);
5603NK_LIB void nk_memset(void *ptr, int c0, nk_size size);
5604NK_LIB void nk_zero(void *ptr, nk_size size);
5605NK_LIB char *nk_itoa(char *s, long n);
5606NK_LIB int nk_string_float_limit(char *string, int prec);
5607NK_LIB char *nk_dtoa(char *s, double n);
5608NK_LIB int nk_text_clamp(const struct nk_user_font *font, const char *text, int text_len, float space, int *glyphs, float *text_width, nk_rune *sep_list, int sep_count);
5609NK_LIB struct nk_vec2 nk_text_calculate_text_bounds(const struct nk_user_font *font, const char *begin, int byte_len, float row_height, const char **remaining, struct nk_vec2 *out_offset, int *glyphs, int op);
5610#ifdef NK_INCLUDE_STANDARD_VARARGS
5611NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args);
5612#endif
5613#ifdef NK_INCLUDE_STANDARD_IO
5614NK_LIB char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc);
5615#endif
5616
5617/* buffer */
5618#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
5619NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size);
5620NK_LIB void nk_mfree(nk_handle unused, void *ptr);
5621#endif
5622NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type);
5623NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align);
5624NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size);
5625
5626/* draw */
5627NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip);
5628NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b);
5629NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size);
5630NK_LIB void nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, struct nk_rect content, struct nk_color background, struct nk_color foreground, float border_width, const struct nk_user_font *font);
5631
5632/* buffering */
5633NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
5634NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win);
5635NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win);
5636NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*);
5637NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
5638NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w);
5639NK_LIB void nk_build(struct nk_context *ctx);
5640
5641/* text editor */
5642NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter);
5643NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
5644NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
5645NK_LIB void nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, const struct nk_user_font *font, float row_height);
5646
5647/* window */
5648enum nk_window_insert_location {
5649 NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
5650 NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
5651};
5652NK_LIB void *nk_create_window(struct nk_context *ctx);
5653NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*);
5654NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win);
5655NK_LIB struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name);
5656NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc);
5657
5658/* pool */
5659NK_LIB void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity);
5660NK_LIB void nk_pool_free(struct nk_pool *pool);
5661NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size);
5662NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool);
5663
5664/* page-element */
5665NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx);
5666NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem);
5667NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem);
5668
5669/* table */
5670NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx);
5671NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
5672NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
5673NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl);
5674NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value);
5675NK_LIB nk_uint *nk_find_value(struct nk_window *win, nk_hash name);
5676
5677/* panel */
5678NK_LIB void *nk_create_panel(struct nk_context *ctx);
5679NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan);
5680NK_LIB int nk_panel_has_header(nk_flags flags, const char *title);
5681NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type);
5682NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type);
5683NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type);
5684NK_LIB int nk_panel_is_sub(enum nk_panel_type type);
5685NK_LIB int nk_panel_is_nonblock(enum nk_panel_type type);
5686NK_LIB int nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type);
5687NK_LIB void nk_panel_end(struct nk_context *ctx);
5688
5689/* layout */
5690NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns);
5691NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols);
5692NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width);
5693NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win);
5694NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify);
5695NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx);
5696NK_LIB void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx);
5697
5698/* popup */
5699NK_LIB int nk_nonblock_begin(struct nk_context *ctx, nk_flags flags, struct nk_rect body, struct nk_rect header, enum nk_panel_type panel_type);
5700
5701/* text */
5702struct nk_text {
5703 struct nk_vec2 padding;
5704 struct nk_color background;
5705 struct nk_color text;
5706};
5707NK_LIB void nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, nk_flags a, const struct nk_user_font *f);
5708NK_LIB void nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, const struct nk_user_font *f);
5709
5710/* button */
5711NK_LIB int nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior);
5712NK_LIB const struct nk_style_item* nk_draw_button(struct nk_command_buffer *out, const struct nk_rect *bounds, nk_flags state, const struct nk_style_button *style);
5713NK_LIB int nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, const struct nk_style_button *style, const struct nk_input *in, enum nk_button_behavior behavior, struct nk_rect *content);
5714NK_LIB void nk_draw_button_text(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const char *txt, int len, nk_flags text_alignment, const struct nk_user_font *font);
5715NK_LIB int nk_do_button_text(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *string, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
5716NK_LIB void nk_draw_button_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, enum nk_symbol_type type, const struct nk_user_font *font);
5717NK_LIB int nk_do_button_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
5718NK_LIB void nk_draw_button_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const struct nk_image *img);
5719NK_LIB int nk_do_button_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, enum nk_button_behavior b, const struct nk_style_button *style, const struct nk_input *in);
5720NK_LIB void nk_draw_button_text_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, const char *str, int len, enum nk_symbol_type type, const struct nk_user_font *font);
5721NK_LIB int nk_do_button_text_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, const char *str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
5722NK_LIB void nk_draw_button_text_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, const char *str, int len, const struct nk_user_font *font, const struct nk_image *img);
5723NK_LIB int nk_do_button_text_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, const char* str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
5724
5725/* toggle */
5726enum nk_toggle_type {
5727 NK_TOGGLE_CHECK,
5728 NK_TOGGLE_OPTION
5729};
5730NK_LIB int nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, int active);
5731NK_LIB void nk_draw_checkbox(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
5732NK_LIB void nk_draw_option(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
5733NK_LIB int nk_do_toggle(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, int *active, const char *str, int len, enum nk_toggle_type type, const struct nk_style_toggle *style, const struct nk_input *in, const struct nk_user_font *font);
5734
5735/* progress */
5736NK_LIB nk_size nk_progress_behavior(nk_flags *state, struct nk_input *in, struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable);
5737NK_LIB void nk_draw_progress(struct nk_command_buffer *out, nk_flags state, const struct nk_style_progress *style, const struct nk_rect *bounds, const struct nk_rect *scursor, nk_size value, nk_size max);
5738NK_LIB nk_size nk_do_progress(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_size value, nk_size max, int modifiable, const struct nk_style_progress *style, struct nk_input *in);
5739
5740/* slider */
5741NK_LIB float nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, struct nk_rect *visual_cursor, struct nk_input *in, struct nk_rect bounds, float slider_min, float slider_max, float slider_value, float slider_step, float slider_steps);
5742NK_LIB void nk_draw_slider(struct nk_command_buffer *out, nk_flags state, const struct nk_style_slider *style, const struct nk_rect *bounds, const struct nk_rect *visual_cursor, float min, float value, float max);
5743NK_LIB float nk_do_slider(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, float min, float val, float max, float step, const struct nk_style_slider *style, struct nk_input *in, const struct nk_user_font *font);
5744
5745/* scrollbar */
5746NK_LIB float nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, int has_scrolling, const struct nk_rect *scroll, const struct nk_rect *cursor, const struct nk_rect *empty0, const struct nk_rect *empty1, float scroll_offset, float target, float scroll_step, enum nk_orientation o);
5747NK_LIB void nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, const struct nk_style_scrollbar *style, const struct nk_rect *bounds, const struct nk_rect *scroll);
5748NK_LIB float nk_do_scrollbarv(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
5749NK_LIB float nk_do_scrollbarh(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
5750
5751/* selectable */
5752NK_LIB void nk_draw_selectable(struct nk_command_buffer *out, nk_flags state, const struct nk_style_selectable *style, int active, const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, const char *string, int len, nk_flags align, const struct nk_user_font *font);
5753NK_LIB int nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
5754NK_LIB int nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_image *img, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
5755
5756/* edit */
5757NK_LIB void nk_edit_draw_text(struct nk_command_buffer *out, const struct nk_style_edit *style, float pos_x, float pos_y, float x_offset, const char *text, int byte_len, float row_height, const struct nk_user_font *font, struct nk_color background, struct nk_color foreground, int is_selected);
5758NK_LIB nk_flags nk_do_edit(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, struct nk_text_edit *edit, const struct nk_style_edit *style, struct nk_input *in, const struct nk_user_font *font);
5759
5760/* color-picker */
5761NK_LIB int nk_color_picker_behavior(nk_flags *state, const struct nk_rect *bounds, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf *color, const struct nk_input *in);
5762NK_LIB void nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf col);
5763NK_LIB int nk_do_color_picker(nk_flags *state, struct nk_command_buffer *out, struct nk_colorf *col, enum nk_color_format fmt, struct nk_rect bounds, struct nk_vec2 padding, const struct nk_input *in, const struct nk_user_font *font);
5764
5765/* property */
5766enum nk_property_status {
5767 NK_PROPERTY_DEFAULT,
5768 NK_PROPERTY_EDIT,
5769 NK_PROPERTY_DRAG
5770};
5771enum nk_property_filter {
5772 NK_FILTER_INT,
5773 NK_FILTER_FLOAT
5774};
5775enum nk_property_kind {
5776 NK_PROPERTY_INT,
5777 NK_PROPERTY_FLOAT,
5778 NK_PROPERTY_DOUBLE
5779};
5780union nk_property {
5781 int i;
5782 float f;
5783 double d;
5784};
5785struct nk_property_variant {
5786 enum nk_property_kind kind;
5787 union nk_property value;
5788 union nk_property min_value;
5789 union nk_property max_value;
5790 union nk_property step;
5791};
5792NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step);
5793NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step);
5794NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step);
5795
5796NK_LIB void nk_drag_behavior(nk_flags *state, const struct nk_input *in, struct nk_rect drag, struct nk_property_variant *variant, float inc_per_pixel);
5797NK_LIB void nk_property_behavior(nk_flags *ws, const struct nk_input *in, struct nk_rect property, struct nk_rect label, struct nk_rect edit, struct nk_rect empty, int *state, struct nk_property_variant *variant, float inc_per_pixel);
5798NK_LIB void nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, const char *name, int len, const struct nk_user_font *font);
5799NK_LIB void nk_do_property(nk_flags *ws, struct nk_command_buffer *out, struct nk_rect property, const char *name, struct nk_property_variant *variant, float inc_per_pixel, char *buffer, int *len, int *state, int *cursor, int *select_begin, int *select_end, const struct nk_style_property *style, enum nk_property_filter filter, struct nk_input *in, const struct nk_user_font *font, struct nk_text_edit *text_edit, enum nk_button_behavior behavior);
5800NK_LIB void nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, float inc_per_pixel, const enum nk_property_filter filter);
5801
5802#endif
5803
5804
5805
5806
5807/* ===============================================================
5808 *
5809 * MATH
5810 *
5811 * ===============================================================*/
5812/* Since nuklear is supposed to work on all systems providing floating point
5813 math without any dependencies I also had to implement my own math functions
5814 for sqrt, sin and cos. Since the actual highly accurate implementations for
5815 the standard library functions are quite complex and I do not need high
5816 precision for my use cases I use approximations.
5817
5818 Sqrt
5819 ----
5820 For square root nuklear uses the famous fast inverse square root:
5821 https://en.wikipedia.org/wiki/Fast_inverse_square_root with
5822 slightly tweaked magic constant. While on today's hardware it is
5823 probably not faster it is still fast and accurate enough for
5824 nuklear's use cases. IMPORTANT: this requires float format IEEE 754
5825
5826 Sine/Cosine
5827 -----------
5828 All constants inside both function are generated Remez's minimax
5829 approximations for value range 0...2*PI. The reason why I decided to
5830 approximate exactly that range is that nuklear only needs sine and
5831 cosine to generate circles which only requires that exact range.
5832 In addition I used Remez instead of Taylor for additional precision:
5833 www.lolengine.net/blog/2011/12/21/better-function-approximations.
5834
5835 The tool I used to generate constants for both sine and cosine
5836 (it can actually approximate a lot more functions) can be
5837 found here: www.lolengine.net/wiki/oss/lolremez
5838*/
5839NK_LIB float
5840nk_inv_sqrt(float n)
5841{
5842 float x2;
5843 const float threehalfs = 1.5f;
5844 union {nk_uint i; float f;} conv = {0};
5845 conv.f = n;
5846 x2 = n * 0.5f;
5847 conv.i = 0x5f375A84 - (conv.i >> 1);
5848 conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
5849 return conv.f;
5850}
5851NK_LIB float
5852nk_sqrt(float x)
5853{
5854 return x * nk_inv_sqrt(x);
5855}
5856NK_LIB float
5857nk_sin(float x)
5858{
5859 NK_STORAGE const float a0 = +1.91059300966915117e-31f;
5860 NK_STORAGE const float a1 = +1.00086760103908896f;
5861 NK_STORAGE const float a2 = -1.21276126894734565e-2f;
5862 NK_STORAGE const float a3 = -1.38078780785773762e-1f;
5863 NK_STORAGE const float a4 = -2.67353392911981221e-2f;
5864 NK_STORAGE const float a5 = +2.08026600266304389e-2f;
5865 NK_STORAGE const float a6 = -3.03996055049204407e-3f;
5866 NK_STORAGE const float a7 = +1.38235642404333740e-4f;
5867 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
5868}
5869NK_LIB float
5870nk_cos(float x)
5871{
5872 // New implementation. Also generated using lolremez.
5873 // Old version significantly deviated from expected results.
5874 NK_STORAGE const float a0 = 9.9995999154986614e-1f;
5875 NK_STORAGE const float a1 = 1.2548995793001028e-3f;
5876 NK_STORAGE const float a2 = -5.0648546280678015e-1f;
5877 NK_STORAGE const float a3 = 1.2942246466519995e-2f;
5878 NK_STORAGE const float a4 = 2.8668384702547972e-2f;
5879 NK_STORAGE const float a5 = 7.3726485210586547e-3f;
5880 NK_STORAGE const float a6 = -3.8510875386947414e-3f;
5881 NK_STORAGE const float a7 = 4.7196604604366623e-4f;
5882 NK_STORAGE const float a8 = -1.8776444013090451e-5f;
5883 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8)))))));
5884}
5886nk_round_up_pow2(nk_uint v)
5887{
5888 v--;
5889 v |= v >> 1;
5890 v |= v >> 2;
5891 v |= v >> 4;
5892 v |= v >> 8;
5893 v |= v >> 16;
5894 v++;
5895 return v;
5896}
5897NK_LIB double
5898nk_pow(double x, int n)
5899{
5900 /* check the sign of n */
5901 double r = 1;
5902 int plus = n >= 0;
5903 n = (plus) ? n : -n;
5904 while (n > 0) {
5905 if ((n & 1) == 1)
5906 r *= x;
5907 n /= 2;
5908 x *= x;
5909 }
5910 return plus ? r : 1.0 / r;
5911}
5912NK_LIB int
5913nk_ifloord(double x)
5914{
5915 x = (double)((int)x - ((x < 0.0) ? 1 : 0));
5916 return (int)x;
5917}
5918NK_LIB int
5919nk_ifloorf(float x)
5920{
5921 x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
5922 return (int)x;
5923}
5924NK_LIB int
5925nk_iceilf(float x)
5926{
5927 if (x >= 0) {
5928 int i = (int)x;
5929 return (x > i) ? i+1: i;
5930 } else {
5931 int t = (int)x;
5932 float r = x - (float)t;
5933 return (r > 0.0f) ? t+1: t;
5934 }
5935}
5936NK_LIB int
5937nk_log10(double n)
5938{
5939 int neg;
5940 int ret;
5941 int exp = 0;
5942
5943 neg = (n < 0) ? 1 : 0;
5944 ret = (neg) ? (int)-n : (int)n;
5945 while ((ret / 10) > 0) {
5946 ret /= 10;
5947 exp++;
5948 }
5949 if (neg) exp = -exp;
5950 return exp;
5951}
5952NK_API struct nk_rect
5953nk_get_null_rect(void)
5954{
5955 return nk_null_rect;
5956}
5957NK_API struct nk_rect
5958nk_rect(float x, float y, float w, float h)
5959{
5960 struct nk_rect r;
5961 r.x = x; r.y = y;
5962 r.w = w; r.h = h;
5963 return r;
5964}
5965NK_API struct nk_rect
5966nk_recti(int x, int y, int w, int h)
5967{
5968 struct nk_rect r;
5969 r.x = (float)x;
5970 r.y = (float)y;
5971 r.w = (float)w;
5972 r.h = (float)h;
5973 return r;
5974}
5975NK_API struct nk_rect
5976nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
5977{
5978 return nk_rect(pos.x, pos.y, size.x, size.y);
5979}
5980NK_API struct nk_rect
5981nk_rectv(const float *r)
5982{
5983 return nk_rect(r[0], r[1], r[2], r[3]);
5984}
5985NK_API struct nk_rect
5986nk_rectiv(const int *r)
5987{
5988 return nk_recti(r[0], r[1], r[2], r[3]);
5989}
5990NK_API struct nk_vec2
5991nk_rect_pos(struct nk_rect r)
5992{
5993 struct nk_vec2 ret;
5994 ret.x = r.x; ret.y = r.y;
5995 return ret;
5996}
5997NK_API struct nk_vec2
5998nk_rect_size(struct nk_rect r)
5999{
6000 struct nk_vec2 ret;
6001 ret.x = r.w; ret.y = r.h;
6002 return ret;
6003}
6004NK_LIB struct nk_rect
6005nk_shrink_rect(struct nk_rect r, float amount)
6006{
6007 struct nk_rect res;
6008 r.w = NK_MAX(r.w, 2 * amount);
6009 r.h = NK_MAX(r.h, 2 * amount);
6010 res.x = r.x + amount;
6011 res.y = r.y + amount;
6012 res.w = r.w - 2 * amount;
6013 res.h = r.h - 2 * amount;
6014 return res;
6015}
6016NK_LIB struct nk_rect
6017nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
6018{
6019 r.w = NK_MAX(r.w, 2 * pad.x);
6020 r.h = NK_MAX(r.h, 2 * pad.y);
6021 r.x += pad.x; r.y += pad.y;
6022 r.w -= 2 * pad.x;
6023 r.h -= 2 * pad.y;
6024 return r;
6025}
6026NK_API struct nk_vec2
6027nk_vec2(float x, float y)
6028{
6029 struct nk_vec2 ret;
6030 ret.x = x; ret.y = y;
6031 return ret;
6032}
6033NK_API struct nk_vec2
6034nk_vec2i(int x, int y)
6035{
6036 struct nk_vec2 ret;
6037 ret.x = (float)x;
6038 ret.y = (float)y;
6039 return ret;
6040}
6041NK_API struct nk_vec2
6042nk_vec2v(const float *v)
6043{
6044 return nk_vec2(v[0], v[1]);
6045}
6046NK_API struct nk_vec2
6047nk_vec2iv(const int *v)
6048{
6049 return nk_vec2i(v[0], v[1]);
6050}
6051NK_LIB void
6052nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
6053 float x1, float y1)
6054{
6055 NK_ASSERT(a);
6056 NK_ASSERT(clip);
6057 clip->x = NK_MAX(a->x, x0);
6058 clip->y = NK_MAX(a->y, y0);
6059 clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
6060 clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
6061 clip->w = NK_MAX(0, clip->w);
6062 clip->h = NK_MAX(0, clip->h);
6063}
6064
6065NK_API void
6066nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
6067 float pad_x, float pad_y, enum nk_heading direction)
6068{
6069 float w_half, h_half;
6070 NK_ASSERT(result);
6071
6072 r.w = NK_MAX(2 * pad_x, r.w);
6073 r.h = NK_MAX(2 * pad_y, r.h);
6074 r.w = r.w - 2 * pad_x;
6075 r.h = r.h - 2 * pad_y;
6076
6077 r.x = r.x + pad_x;
6078 r.y = r.y + pad_y;
6079
6080 w_half = r.w / 2.0f;
6081 h_half = r.h / 2.0f;
6082
6083 if (direction == NK_UP) {
6084 result[0] = nk_vec2(r.x + w_half, r.y);
6085 result[1] = nk_vec2(r.x + r.w, r.y + r.h);
6086 result[2] = nk_vec2(r.x, r.y + r.h);
6087 } else if (direction == NK_RIGHT) {
6088 result[0] = nk_vec2(r.x, r.y);
6089 result[1] = nk_vec2(r.x + r.w, r.y + h_half);
6090 result[2] = nk_vec2(r.x, r.y + r.h);
6091 } else if (direction == NK_DOWN) {
6092 result[0] = nk_vec2(r.x, r.y);
6093 result[1] = nk_vec2(r.x + r.w, r.y);
6094 result[2] = nk_vec2(r.x + w_half, r.y + r.h);
6095 } else {
6096 result[0] = nk_vec2(r.x, r.y + h_half);
6097 result[1] = nk_vec2(r.x + r.w, r.y);
6098 result[2] = nk_vec2(r.x + r.w, r.y + r.h);
6099 }
6100}
6101
6102
6103
6104
6105/* ===============================================================
6106 *
6107 * UTIL
6108 *
6109 * ===============================================================*/
6110NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
6111NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
6112NK_LIB int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
6113NK_LIB int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
6114NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
6115NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
6116
6117NK_LIB void*
6118nk_memcopy(void *dst0, const void *src0, nk_size length)
6119{
6120 nk_ptr t;
6121 char *dst = (char*)dst0;
6122 const char *src = (const char*)src0;
6123 if (length == 0 || dst == src)
6124 goto done;
6125
6126 #define nk_word int
6127 #define nk_wsize sizeof(nk_word)
6128 #define nk_wmask (nk_wsize-1)
6129 #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
6130 #define NK_TLOOP1(s) do { s; } while (--t)
6131
6132 if (dst < src) {
6133 t = (nk_ptr)src; /* only need low bits */
6134 if ((t | (nk_ptr)dst) & nk_wmask) {
6135 if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
6136 t = length;
6137 else
6138 t = nk_wsize - (t & nk_wmask);
6139 length -= t;
6140 NK_TLOOP1(*dst++ = *src++);
6141 }
6142 t = length / nk_wsize;
6143 NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
6144 src += nk_wsize; dst += nk_wsize);
6145 t = length & nk_wmask;
6146 NK_TLOOP(*dst++ = *src++);
6147 } else {
6148 src += length;
6149 dst += length;
6150 t = (nk_ptr)src;
6151 if ((t | (nk_ptr)dst) & nk_wmask) {
6152 if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
6153 t = length;
6154 else
6155 t &= nk_wmask;
6156 length -= t;
6157 NK_TLOOP1(*--dst = *--src);
6158 }
6159 t = length / nk_wsize;
6160 NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
6161 *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
6162 t = length & nk_wmask;
6163 NK_TLOOP(*--dst = *--src);
6164 }
6165 #undef nk_word
6166 #undef nk_wsize
6167 #undef nk_wmask
6168 #undef NK_TLOOP
6169 #undef NK_TLOOP1
6170done:
6171 return (dst0);
6172}
6173NK_LIB void
6174nk_memset(void *ptr, int c0, nk_size size)
6175{
6176 #define nk_word unsigned
6177 #define nk_wsize sizeof(nk_word)
6178 #define nk_wmask (nk_wsize - 1)
6179 nk_byte *dst = (nk_byte*)ptr;
6180 unsigned c = 0;
6181 nk_size t = 0;
6182
6183 if ((c = (nk_byte)c0) != 0) {
6184 c = (c << 8) | c; /* at least 16-bits */
6185 if (sizeof(unsigned int) > 2)
6186 c = (c << 16) | c; /* at least 32-bits*/
6187 }
6188
6189 /* too small of a word count */
6190 dst = (nk_byte*)ptr;
6191 if (size < 3 * nk_wsize) {
6192 while (size--) *dst++ = (nk_byte)c0;
6193 return;
6194 }
6195
6196 /* align destination */
6197 if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
6198 t = nk_wsize -t;
6199 size -= t;
6200 do {
6201 *dst++ = (nk_byte)c0;
6202 } while (--t != 0);
6203 }
6204
6205 /* fill word */
6206 t = size / nk_wsize;
6207 do {
6208 *(nk_word*)((void*)dst) = c;
6209 dst += nk_wsize;
6210 } while (--t != 0);
6211
6212 /* fill trailing bytes */
6213 t = (size & nk_wmask);
6214 if (t != 0) {
6215 do {
6216 *dst++ = (nk_byte)c0;
6217 } while (--t != 0);
6218 }
6219
6220 #undef nk_word
6221 #undef nk_wsize
6222 #undef nk_wmask
6223}
6224NK_LIB void
6225nk_zero(void *ptr, nk_size size)
6226{
6227 NK_ASSERT(ptr);
6228 NK_MEMSET(ptr, 0, size);
6229}
6230NK_API int
6231nk_strlen(const char *str)
6232{
6233 int siz = 0;
6234 NK_ASSERT(str);
6235 while (str && *str++ != '\0') siz++;
6236 return siz;
6237}
6238NK_API int
6239nk_strtoi(const char *str, const char **endptr)
6240{
6241 int neg = 1;
6242 const char *p = str;
6243 int value = 0;
6244
6245 NK_ASSERT(str);
6246 if (!str) return 0;
6247
6248 /* skip whitespace */
6249 while (*p == ' ') p++;
6250 if (*p == '-') {
6251 neg = -1;
6252 p++;
6253 }
6254 while (*p && *p >= '0' && *p <= '9') {
6255 value = value * 10 + (int) (*p - '0');
6256 p++;
6257 }
6258 if (endptr)
6259 *endptr = p;
6260 return neg*value;
6261}
6262NK_API double
6263nk_strtod(const char *str, const char **endptr)
6264{
6265 double m;
6266 double neg = 1.0;
6267 const char *p = str;
6268 double value = 0;
6269 double number = 0;
6270
6271 NK_ASSERT(str);
6272 if (!str) return 0;
6273
6274 /* skip whitespace */
6275 while (*p == ' ') p++;
6276 if (*p == '-') {
6277 neg = -1.0;
6278 p++;
6279 }
6280
6281 while (*p && *p != '.' && *p != 'e') {
6282 value = value * 10.0 + (double) (*p - '0');
6283 p++;
6284 }
6285
6286 if (*p == '.') {
6287 p++;
6288 for(m = 0.1; *p && *p != 'e'; p++ ) {
6289 value = value + (double) (*p - '0') * m;
6290 m *= 0.1;
6291 }
6292 }
6293 if (*p == 'e') {
6294 int i, pow, div;
6295 p++;
6296 if (*p == '-') {
6297 div = nk_true;
6298 p++;
6299 } else if (*p == '+') {
6300 div = nk_false;
6301 p++;
6302 } else div = nk_false;
6303
6304 for (pow = 0; *p; p++)
6305 pow = pow * 10 + (int) (*p - '0');
6306
6307 for (m = 1.0, i = 0; i < pow; i++)
6308 m *= 10.0;
6309
6310 if (div)
6311 value /= m;
6312 else value *= m;
6313 }
6314 number = value * neg;
6315 if (endptr)
6316 *endptr = p;
6317 return number;
6318}
6319NK_API float
6320nk_strtof(const char *str, const char **endptr)
6321{
6322 float float_value;
6323 double double_value;
6324 double_value = NK_STRTOD(str, endptr);
6325 float_value = (float)double_value;
6326 return float_value;
6327}
6328NK_API int
6329nk_stricmp(const char *s1, const char *s2)
6330{
6331 nk_int c1,c2,d;
6332 do {
6333 c1 = *s1++;
6334 c2 = *s2++;
6335 d = c1 - c2;
6336 while (d) {
6337 if (c1 <= 'Z' && c1 >= 'A') {
6338 d += ('a' - 'A');
6339 if (!d) break;
6340 }
6341 if (c2 <= 'Z' && c2 >= 'A') {
6342 d -= ('a' - 'A');
6343 if (!d) break;
6344 }
6345 return ((d >= 0) << 1) - 1;
6346 }
6347 } while (c1);
6348 return 0;
6349}
6350NK_API int
6351nk_stricmpn(const char *s1, const char *s2, int n)
6352{
6353 int c1,c2,d;
6354 NK_ASSERT(n >= 0);
6355 do {
6356 c1 = *s1++;
6357 c2 = *s2++;
6358 if (!n--) return 0;
6359
6360 d = c1 - c2;
6361 while (d) {
6362 if (c1 <= 'Z' && c1 >= 'A') {
6363 d += ('a' - 'A');
6364 if (!d) break;
6365 }
6366 if (c2 <= 'Z' && c2 >= 'A') {
6367 d -= ('a' - 'A');
6368 if (!d) break;
6369 }
6370 return ((d >= 0) << 1) - 1;
6371 }
6372 } while (c1);
6373 return 0;
6374}
6375NK_INTERN int
6376nk_str_match_here(const char *regexp, const char *text)
6377{
6378 if (regexp[0] == '\0')
6379 return 1;
6380 if (regexp[1] == '*')
6381 return nk_str_match_star(regexp[0], regexp+2, text);
6382 if (regexp[0] == '$' && regexp[1] == '\0')
6383 return *text == '\0';
6384 if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
6385 return nk_str_match_here(regexp+1, text+1);
6386 return 0;
6387}
6388NK_INTERN int
6389nk_str_match_star(int c, const char *regexp, const char *text)
6390{
6391 do {/* a '* matches zero or more instances */
6392 if (nk_str_match_here(regexp, text))
6393 return 1;
6394 } while (*text != '\0' && (*text++ == c || c == '.'));
6395 return 0;
6396}
6397NK_API int
6398nk_strfilter(const char *text, const char *regexp)
6399{
6400 /*
6401 c matches any literal character c
6402 . matches any single character
6403 ^ matches the beginning of the input string
6404 $ matches the end of the input string
6405 * matches zero or more occurrences of the previous character*/
6406 if (regexp[0] == '^')
6407 return nk_str_match_here(regexp+1, text);
6408 do { /* must look even if string is empty */
6409 if (nk_str_match_here(regexp, text))
6410 return 1;
6411 } while (*text++ != '\0');
6412 return 0;
6413}
6414NK_API int
6415nk_strmatch_fuzzy_text(const char *str, int str_len,
6416 const char *pattern, int *out_score)
6417{
6418 /* Returns true if each character in pattern is found sequentially within str
6419 * if found then out_score is also set. Score value has no intrinsic meaning.
6420 * Range varies with pattern. Can only compare scores with same search pattern. */
6421
6422 /* bonus for adjacent matches */
6423 #define NK_ADJACENCY_BONUS 5
6424 /* bonus if match occurs after a separator */
6425 #define NK_SEPARATOR_BONUS 10
6426 /* bonus if match is uppercase and prev is lower */
6427 #define NK_CAMEL_BONUS 10
6428 /* penalty applied for every letter in str before the first match */
6429 #define NK_LEADING_LETTER_PENALTY (-3)
6430 /* maximum penalty for leading letters */
6431 #define NK_MAX_LEADING_LETTER_PENALTY (-9)
6432 /* penalty for every letter that doesn't matter */
6433 #define NK_UNMATCHED_LETTER_PENALTY (-1)
6434
6435 /* loop variables */
6436 int score = 0;
6437 char const * pattern_iter = pattern;
6438 int str_iter = 0;
6439 int prev_matched = nk_false;
6440 int prev_lower = nk_false;
6441 /* true so if first letter match gets separator bonus*/
6442 int prev_separator = nk_true;
6443
6444 /* use "best" matched letter if multiple string letters match the pattern */
6445 char const * best_letter = 0;
6446 int best_letter_score = 0;
6447
6448 /* loop over strings */
6449 NK_ASSERT(str);
6450 NK_ASSERT(pattern);
6451 if (!str || !str_len || !pattern) return 0;
6452 while (str_iter < str_len)
6453 {
6454 const char pattern_letter = *pattern_iter;
6455 const char str_letter = str[str_iter];
6456
6457 int next_match = *pattern_iter != '\0' &&
6458 nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
6459 int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
6460
6461 int advanced = next_match && best_letter;
6462 int pattern_repeat = best_letter && *pattern_iter != '\0';
6463 pattern_repeat = pattern_repeat &&
6464 nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
6465
6466 if (advanced || pattern_repeat) {
6467 score += best_letter_score;
6468 best_letter = 0;
6469 best_letter_score = 0;
6470 }
6471
6472 if (next_match || rematch)
6473 {
6474 int new_score = 0;
6475 /* Apply penalty for each letter before the first pattern match */
6476 if (pattern_iter == pattern) {
6477 int count = (int)(&str[str_iter] - str);
6478 int penalty = NK_LEADING_LETTER_PENALTY * count;
6479 if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
6480 penalty = NK_MAX_LEADING_LETTER_PENALTY;
6481
6482 score += penalty;
6483 }
6484
6485 /* apply bonus for consecutive bonuses */
6486 if (prev_matched)
6487 new_score += NK_ADJACENCY_BONUS;
6488
6489 /* apply bonus for matches after a separator */
6490 if (prev_separator)
6491 new_score += NK_SEPARATOR_BONUS;
6492
6493 /* apply bonus across camel case boundaries */
6494 if (prev_lower && nk_is_upper(str_letter))
6495 new_score += NK_CAMEL_BONUS;
6496
6497 /* update pattern iter IFF the next pattern letter was matched */
6498 if (next_match)
6499 ++pattern_iter;
6500
6501 /* update best letter in str which may be for a "next" letter or a rematch */
6502 if (new_score >= best_letter_score) {
6503 /* apply penalty for now skipped letter */
6504 if (best_letter != 0)
6505 score += NK_UNMATCHED_LETTER_PENALTY;
6506
6507 best_letter = &str[str_iter];
6508 best_letter_score = new_score;
6509 }
6510 prev_matched = nk_true;
6511 } else {
6512 score += NK_UNMATCHED_LETTER_PENALTY;
6513 prev_matched = nk_false;
6514 }
6515
6516 /* separators should be more easily defined */
6517 prev_lower = nk_is_lower(str_letter) != 0;
6518 prev_separator = str_letter == '_' || str_letter == ' ';
6519
6520 ++str_iter;
6521 }
6522
6523 /* apply score for last match */
6524 if (best_letter)
6525 score += best_letter_score;
6526
6527 /* did not match full pattern */
6528 if (*pattern_iter != '\0')
6529 return nk_false;
6530
6531 if (out_score)
6532 *out_score = score;
6533 return nk_true;
6534}
6535NK_API int
6536nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
6537{
6538 return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);
6539}
6540NK_LIB int
6541nk_string_float_limit(char *string, int prec)
6542{
6543 int dot = 0;
6544 char *c = string;
6545 while (*c) {
6546 if (*c == '.') {
6547 dot = 1;
6548 c++;
6549 continue;
6550 }
6551 if (dot == (prec+1)) {
6552 *c = 0;
6553 break;
6554 }
6555 if (dot > 0) dot++;
6556 c++;
6557 }
6558 return (int)(c - string);
6559}
6560NK_INTERN void
6561nk_strrev_ascii(char *s)
6562{
6563 int len = nk_strlen(s);
6564 int end = len / 2;
6565 int i = 0;
6566 char t;
6567 for (; i < end; ++i) {
6568 t = s[i];
6569 s[i] = s[len - 1 - i];
6570 s[len -1 - i] = t;
6571 }
6572}
6573NK_LIB char*
6574nk_itoa(char *s, long n)
6575{
6576 long i = 0;
6577 if (n == 0) {
6578 s[i++] = '0';
6579 s[i] = 0;
6580 return s;
6581 }
6582 if (n < 0) {
6583 s[i++] = '-';
6584 n = -n;
6585 }
6586 while (n > 0) {
6587 s[i++] = (char)('0' + (n % 10));
6588 n /= 10;
6589 }
6590 s[i] = 0;
6591 if (s[0] == '-')
6592 ++s;
6593
6594 nk_strrev_ascii(s);
6595 return s;
6596}
6597NK_LIB char*
6598nk_dtoa(char *s, double n)
6599{
6600 int useExp = 0;
6601 int digit = 0, m = 0, m1 = 0;
6602 char *c = s;
6603 int neg = 0;
6604
6605 NK_ASSERT(s);
6606 if (!s) return 0;
6607
6608 if (n == 0.0) {
6609 s[0] = '0'; s[1] = '\0';
6610 return s;
6611 }
6612
6613 neg = (n < 0);
6614 if (neg) n = -n;
6615
6616 /* calculate magnitude */
6617 m = nk_log10(n);
6618 useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
6619 if (neg) *(c++) = '-';
6620
6621 /* set up for scientific notation */
6622 if (useExp) {
6623 if (m < 0)
6624 m -= 1;
6625 n = n / (double)nk_pow(10.0, m);
6626 m1 = m;
6627 m = 0;
6628 }
6629 if (m < 1.0) {
6630 m = 0;
6631 }
6632
6633 /* convert the number */
6634 while (n > NK_FLOAT_PRECISION || m >= 0) {
6635 double weight = nk_pow(10.0, m);
6636 if (weight > 0) {
6637 double t = (double)n / weight;
6638 digit = nk_ifloord(t);
6639 n -= ((double)digit * weight);
6640 *(c++) = (char)('0' + (char)digit);
6641 }
6642 if (m == 0 && n > 0)
6643 *(c++) = '.';
6644 m--;
6645 }
6646
6647 if (useExp) {
6648 /* convert the exponent */
6649 int i, j;
6650 *(c++) = 'e';
6651 if (m1 > 0) {
6652 *(c++) = '+';
6653 } else {
6654 *(c++) = '-';
6655 m1 = -m1;
6656 }
6657 m = 0;
6658 while (m1 > 0) {
6659 *(c++) = (char)('0' + (char)(m1 % 10));
6660 m1 /= 10;
6661 m++;
6662 }
6663 c -= m;
6664 for (i = 0, j = m-1; i<j; i++, j--) {
6665 /* swap without temporary */
6666 c[i] ^= c[j];
6667 c[j] ^= c[i];
6668 c[i] ^= c[j];
6669 }
6670 c += m;
6671 }
6672 *(c) = '\0';
6673 return s;
6674}
6675#ifdef NK_INCLUDE_STANDARD_VARARGS
6676#ifndef NK_INCLUDE_STANDARD_IO
6677NK_INTERN int
6678nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
6679{
6680 enum nk_arg_type {
6681 NK_ARG_TYPE_CHAR,
6682 NK_ARG_TYPE_SHORT,
6683 NK_ARG_TYPE_DEFAULT,
6684 NK_ARG_TYPE_LONG
6685 };
6686 enum nk_arg_flags {
6687 NK_ARG_FLAG_LEFT = 0x01,
6688 NK_ARG_FLAG_PLUS = 0x02,
6689 NK_ARG_FLAG_SPACE = 0x04,
6690 NK_ARG_FLAG_NUM = 0x10,
6691 NK_ARG_FLAG_ZERO = 0x20
6692 };
6693
6694 char number_buffer[NK_MAX_NUMBER_BUFFER];
6695 enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
6696 int precision = NK_DEFAULT;
6697 int width = NK_DEFAULT;
6698 nk_flags flag = 0;
6699
6700 int len = 0;
6701 int result = -1;
6702 const char *iter = fmt;
6703
6704 NK_ASSERT(buf);
6705 NK_ASSERT(buf_size);
6706 if (!buf || !buf_size || !fmt) return 0;
6707 for (iter = fmt; *iter && len < buf_size; iter++) {
6708 /* copy all non-format characters */
6709 while (*iter && (*iter != '%') && (len < buf_size))
6710 buf[len++] = *iter++;
6711 if (!(*iter) || len >= buf_size) break;
6712 iter++;
6713
6714 /* flag arguments */
6715 while (*iter) {
6716 if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
6717 else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
6718 else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
6719 else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
6720 else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
6721 else break;
6722 iter++;
6723 }
6724
6725 /* width argument */
6726 width = NK_DEFAULT;
6727 if (*iter >= '1' && *iter <= '9') {
6728 const char *end;
6729 width = nk_strtoi(iter, &end);
6730 if (end == iter)
6731 width = -1;
6732 else iter = end;
6733 } else if (*iter == '*') {
6734 width = va_arg(args, int);
6735 iter++;
6736 }
6737
6738 /* precision argument */
6739 precision = NK_DEFAULT;
6740 if (*iter == '.') {
6741 iter++;
6742 if (*iter == '*') {
6743 precision = va_arg(args, int);
6744 iter++;
6745 } else {
6746 const char *end;
6747 precision = nk_strtoi(iter, &end);
6748 if (end == iter)
6749 precision = -1;
6750 else iter = end;
6751 }
6752 }
6753
6754 /* length modifier */
6755 if (*iter == 'h') {
6756 if (*(iter+1) == 'h') {
6757 arg_type = NK_ARG_TYPE_CHAR;
6758 iter++;
6759 } else arg_type = NK_ARG_TYPE_SHORT;
6760 iter++;
6761 } else if (*iter == 'l') {
6762 arg_type = NK_ARG_TYPE_LONG;
6763 iter++;
6764 } else arg_type = NK_ARG_TYPE_DEFAULT;
6765
6766 /* specifier */
6767 if (*iter == '%') {
6768 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6769 NK_ASSERT(precision == NK_DEFAULT);
6770 NK_ASSERT(width == NK_DEFAULT);
6771 if (len < buf_size)
6772 buf[len++] = '%';
6773 } else if (*iter == 's') {
6774 /* string */
6775 const char *str = va_arg(args, const char*);
6776 NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
6777 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6778 NK_ASSERT(precision == NK_DEFAULT);
6779 NK_ASSERT(width == NK_DEFAULT);
6780 if (str == buf) return -1;
6781 while (str && *str && len < buf_size)
6782 buf[len++] = *str++;
6783 } else if (*iter == 'n') {
6784 /* current length callback */
6785 signed int *n = va_arg(args, int*);
6786 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6787 NK_ASSERT(precision == NK_DEFAULT);
6788 NK_ASSERT(width == NK_DEFAULT);
6789 if (n) *n = len;
6790 } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
6791 /* signed integer */
6792 long value = 0;
6793 const char *num_iter;
6794 int num_len, num_print, padding;
6795 int cur_precision = NK_MAX(precision, 1);
6796 int cur_width = NK_MAX(width, 0);
6797
6798 /* retrieve correct value type */
6799 if (arg_type == NK_ARG_TYPE_CHAR)
6800 value = (signed char)va_arg(args, int);
6801 else if (arg_type == NK_ARG_TYPE_SHORT)
6802 value = (signed short)va_arg(args, int);
6803 else if (arg_type == NK_ARG_TYPE_LONG)
6804 value = va_arg(args, signed long);
6805 else if (*iter == 'c')
6806 value = (unsigned char)va_arg(args, int);
6807 else value = va_arg(args, signed int);
6808
6809 /* convert number to string */
6810 nk_itoa(number_buffer, value);
6811 num_len = nk_strlen(number_buffer);
6812 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
6813 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
6814 padding = NK_MAX(padding-1, 0);
6815
6816 /* fill left padding up to a total of `width` characters */
6817 if (!(flag & NK_ARG_FLAG_LEFT)) {
6818 while (padding-- > 0 && (len < buf_size)) {
6819 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
6820 buf[len++] = '0';
6821 else buf[len++] = ' ';
6822 }
6823 }
6824
6825 /* copy string value representation into buffer */
6826 if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
6827 buf[len++] = '+';
6828 else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
6829 buf[len++] = ' ';
6830
6831 /* fill up to precision number of digits with '0' */
6832 num_print = NK_MAX(cur_precision, num_len);
6833 while (precision && (num_print > num_len) && (len < buf_size)) {
6834 buf[len++] = '0';
6835 num_print--;
6836 }
6837
6838 /* copy string value representation into buffer */
6839 num_iter = number_buffer;
6840 while (precision && *num_iter && len < buf_size)
6841 buf[len++] = *num_iter++;
6842
6843 /* fill right padding up to width characters */
6844 if (flag & NK_ARG_FLAG_LEFT) {
6845 while ((padding-- > 0) && (len < buf_size))
6846 buf[len++] = ' ';
6847 }
6848 } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
6849 /* unsigned integer */
6850 unsigned long value = 0;
6851 int num_len = 0, num_print, padding = 0;
6852 int cur_precision = NK_MAX(precision, 1);
6853 int cur_width = NK_MAX(width, 0);
6854 unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
6855
6856 /* print oct/hex/dec value */
6857 const char *upper_output_format = "0123456789ABCDEF";
6858 const char *lower_output_format = "0123456789abcdef";
6859 const char *output_format = (*iter == 'x') ?
6860 lower_output_format: upper_output_format;
6861
6862 /* retrieve correct value type */
6863 if (arg_type == NK_ARG_TYPE_CHAR)
6864 value = (unsigned char)va_arg(args, int);
6865 else if (arg_type == NK_ARG_TYPE_SHORT)
6866 value = (unsigned short)va_arg(args, int);
6867 else if (arg_type == NK_ARG_TYPE_LONG)
6868 value = va_arg(args, unsigned long);
6869 else value = va_arg(args, unsigned int);
6870
6871 do {
6872 /* convert decimal number into hex/oct number */
6873 int digit = output_format[value % base];
6874 if (num_len < NK_MAX_NUMBER_BUFFER)
6875 number_buffer[num_len++] = (char)digit;
6876 value /= base;
6877 } while (value > 0);
6878
6879 num_print = NK_MAX(cur_precision, num_len);
6880 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
6881 if (flag & NK_ARG_FLAG_NUM)
6882 padding = NK_MAX(padding-1, 0);
6883
6884 /* fill left padding up to a total of `width` characters */
6885 if (!(flag & NK_ARG_FLAG_LEFT)) {
6886 while ((padding-- > 0) && (len < buf_size)) {
6887 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
6888 buf[len++] = '0';
6889 else buf[len++] = ' ';
6890 }
6891 }
6892
6893 /* fill up to precision number of digits */
6894 if (num_print && (flag & NK_ARG_FLAG_NUM)) {
6895 if ((*iter == 'o') && (len < buf_size)) {
6896 buf[len++] = '0';
6897 } else if ((*iter == 'x') && ((len+1) < buf_size)) {
6898 buf[len++] = '0';
6899 buf[len++] = 'x';
6900 } else if ((*iter == 'X') && ((len+1) < buf_size)) {
6901 buf[len++] = '0';
6902 buf[len++] = 'X';
6903 }
6904 }
6905 while (precision && (num_print > num_len) && (len < buf_size)) {
6906 buf[len++] = '0';
6907 num_print--;
6908 }
6909
6910 /* reverse number direction */
6911 while (num_len > 0) {
6912 if (precision && (len < buf_size))
6913 buf[len++] = number_buffer[num_len-1];
6914 num_len--;
6915 }
6916
6917 /* fill right padding up to width characters */
6918 if (flag & NK_ARG_FLAG_LEFT) {
6919 while ((padding-- > 0) && (len < buf_size))
6920 buf[len++] = ' ';
6921 }
6922 } else if (*iter == 'f') {
6923 /* floating point */
6924 const char *num_iter;
6925 int cur_precision = (precision < 0) ? 6: precision;
6926 int prefix, cur_width = NK_MAX(width, 0);
6927 double value = va_arg(args, double);
6928 int num_len = 0, frac_len = 0, dot = 0;
6929 int padding = 0;
6930
6931 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6932 NK_DTOA(number_buffer, value);
6933 num_len = nk_strlen(number_buffer);
6934
6935 /* calculate padding */
6936 num_iter = number_buffer;
6937 while (*num_iter && *num_iter != '.')
6938 num_iter++;
6939
6940 prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
6941 padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
6942 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
6943 padding = NK_MAX(padding-1, 0);
6944
6945 /* fill left padding up to a total of `width` characters */
6946 if (!(flag & NK_ARG_FLAG_LEFT)) {
6947 while (padding-- > 0 && (len < buf_size)) {
6948 if (flag & NK_ARG_FLAG_ZERO)
6949 buf[len++] = '0';
6950 else buf[len++] = ' ';
6951 }
6952 }
6953
6954 /* copy string value representation into buffer */
6955 num_iter = number_buffer;
6956 if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
6957 buf[len++] = '+';
6958 else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
6959 buf[len++] = ' ';
6960 while (*num_iter) {
6961 if (dot) frac_len++;
6962 if (len < buf_size)
6963 buf[len++] = *num_iter;
6964 if (*num_iter == '.') dot = 1;
6965 if (frac_len >= cur_precision) break;
6966 num_iter++;
6967 }
6968
6969 /* fill number up to precision */
6970 while (frac_len < cur_precision) {
6971 if (!dot && len < buf_size) {
6972 buf[len++] = '.';
6973 dot = 1;
6974 }
6975 if (len < buf_size)
6976 buf[len++] = '0';
6977 frac_len++;
6978 }
6979
6980 /* fill right padding up to width characters */
6981 if (flag & NK_ARG_FLAG_LEFT) {
6982 while ((padding-- > 0) && (len < buf_size))
6983 buf[len++] = ' ';
6984 }
6985 } else {
6986 /* Specifier not supported: g,G,e,E,p,z */
6987 NK_ASSERT(0 && "specifier is not supported!");
6988 return result;
6989 }
6990 }
6991 buf[(len >= buf_size)?(buf_size-1):len] = 0;
6992 result = (len >= buf_size)?-1:len;
6993 return result;
6994}
6995#endif
6996NK_LIB int
6997nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
6998{
6999 int result = -1;
7000 NK_ASSERT(buf);
7001 NK_ASSERT(buf_size);
7002 if (!buf || !buf_size || !fmt) return 0;
7003#ifdef NK_INCLUDE_STANDARD_IO
7004 result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
7005 result = (result >= buf_size) ? -1: result;
7006 buf[buf_size-1] = 0;
7007#else
7008 result = nk_vsnprintf(buf, buf_size, fmt, args);
7009#endif
7010 return result;
7011}
7012#endif
7014nk_murmur_hash(const void * key, int len, nk_hash seed)
7015{
7016 /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
7017 #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
7018
7019 nk_uint h1 = seed;
7020 nk_uint k1;
7021 const nk_byte *data = (const nk_byte*)key;
7022 const nk_byte *keyptr = data;
7023 nk_byte *k1ptr;
7024 const int bsize = sizeof(k1);
7025 const int nblocks = len/4;
7026
7027 const nk_uint c1 = 0xcc9e2d51;
7028 const nk_uint c2 = 0x1b873593;
7029 const nk_byte *tail;
7030 int i;
7031
7032 /* body */
7033 if (!key) return 0;
7034 for (i = 0; i < nblocks; ++i, keyptr += bsize) {
7035 k1ptr = (nk_byte*)&k1;
7036 k1ptr[0] = keyptr[0];
7037 k1ptr[1] = keyptr[1];
7038 k1ptr[2] = keyptr[2];
7039 k1ptr[3] = keyptr[3];
7040
7041 k1 *= c1;
7042 k1 = NK_ROTL(k1,15);
7043 k1 *= c2;
7044
7045 h1 ^= k1;
7046 h1 = NK_ROTL(h1,13);
7047 h1 = h1*5+0xe6546b64;
7048 }
7049
7050 /* tail */
7051 tail = (const nk_byte*)(data + nblocks*4);
7052 k1 = 0;
7053 switch (len & 3) {
7054 case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
7055 case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
7056 case 1: k1 ^= tail[0];
7057 k1 *= c1;
7058 k1 = NK_ROTL(k1,15);
7059 k1 *= c2;
7060 h1 ^= k1;
7061 break;
7062 default: break;
7063 }
7064
7065 /* finalization */
7066 h1 ^= (nk_uint)len;
7067 /* fmix32 */
7068 h1 ^= h1 >> 16;
7069 h1 *= 0x85ebca6b;
7070 h1 ^= h1 >> 13;
7071 h1 *= 0xc2b2ae35;
7072 h1 ^= h1 >> 16;
7073
7074 #undef NK_ROTL
7075 return h1;
7076}
7077#ifdef NK_INCLUDE_STANDARD_IO
7078NK_LIB char*
7079nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
7080{
7081 char *buf;
7082 FILE *fd;
7083 long ret;
7084
7085 NK_ASSERT(path);
7086 NK_ASSERT(siz);
7087 NK_ASSERT(alloc);
7088 if (!path || !siz || !alloc)
7089 return 0;
7090
7091 fd = fopen(path, "rb");
7092 if (!fd) return 0;
7093 fseek(fd, 0, SEEK_END);
7094 ret = ftell(fd);
7095 if (ret < 0) {
7096 fclose(fd);
7097 return 0;
7098 }
7099 *siz = (nk_size)ret;
7100 fseek(fd, 0, SEEK_SET);
7101 buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
7102 NK_ASSERT(buf);
7103 if (!buf) {
7104 fclose(fd);
7105 return 0;
7106 }
7107 *siz = (nk_size)fread(buf, 1,*siz, fd);
7108 fclose(fd);
7109 return buf;
7110}
7111#endif
7112NK_LIB int
7113nk_text_clamp(const struct nk_user_font *font, const char *text,
7114 int text_len, float space, int *glyphs, float *text_width,
7115 nk_rune *sep_list, int sep_count)
7116{
7117 int i = 0;
7118 int glyph_len = 0;
7119 float last_width = 0;
7120 nk_rune unicode = 0;
7121 float width = 0;
7122 int len = 0;
7123 int g = 0;
7124 float s;
7125
7126 int sep_len = 0;
7127 int sep_g = 0;
7128 float sep_width = 0;
7129 sep_count = NK_MAX(sep_count,0);
7130
7131 glyph_len = nk_utf_decode(text, &unicode, text_len);
7132 while (glyph_len && (width < space) && (len < text_len)) {
7133 len += glyph_len;
7134 s = font->width(font->userdata, font->height, text, len);
7135 for (i = 0; i < sep_count; ++i) {
7136 if (unicode != sep_list[i]) continue;
7137 sep_width = last_width = width;
7138 sep_g = g+1;
7139 sep_len = len;
7140 break;
7141 }
7142 if (i == sep_count){
7143 last_width = sep_width = width;
7144 sep_g = g+1;
7145 }
7146 width = s;
7147 glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
7148 g++;
7149 }
7150 if (len >= text_len) {
7151 *glyphs = g;
7152 *text_width = last_width;
7153 return len;
7154 } else {
7155 *glyphs = sep_g;
7156 *text_width = sep_width;
7157 return (!sep_len) ? len: sep_len;
7158 }
7159}
7160NK_LIB struct nk_vec2
7161nk_text_calculate_text_bounds(const struct nk_user_font *font,
7162 const char *begin, int byte_len, float row_height, const char **remaining,
7163 struct nk_vec2 *out_offset, int *glyphs, int op)
7164{
7165 float line_height = row_height;
7166 struct nk_vec2 text_size = nk_vec2(0,0);
7167 float line_width = 0.0f;
7168
7169 float glyph_width;
7170 int glyph_len = 0;
7171 nk_rune unicode = 0;
7172 int text_len = 0;
7173 if (!begin || byte_len <= 0 || !font)
7174 return nk_vec2(0,row_height);
7175
7176 glyph_len = nk_utf_decode(begin, &unicode, byte_len);
7177 if (!glyph_len) return text_size;
7178 glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
7179
7180 *glyphs = 0;
7181 while ((text_len < byte_len) && glyph_len) {
7182 if (unicode == '\n') {
7183 text_size.x = NK_MAX(text_size.x, line_width);
7184 text_size.y += line_height;
7185 line_width = 0;
7186 *glyphs+=1;
7187 if (op == NK_STOP_ON_NEW_LINE)
7188 break;
7189
7190 text_len++;
7191 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7192 continue;
7193 }
7194
7195 if (unicode == '\r') {
7196 text_len++;
7197 *glyphs+=1;
7198 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7199 continue;
7200 }
7201
7202 *glyphs = *glyphs + 1;
7203 text_len += glyph_len;
7204 line_width += (float)glyph_width;
7205 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7206 glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
7207 continue;
7208 }
7209
7210 if (text_size.x < line_width)
7211 text_size.x = line_width;
7212 if (out_offset)
7213 *out_offset = nk_vec2(line_width, text_size.y + line_height);
7214 if (line_width > 0 || text_size.y == 0.0f)
7215 text_size.y += line_height;
7216 if (remaining)
7217 *remaining = begin+text_len;
7218 return text_size;
7219}
7220
7221
7222
7223
7224/* ==============================================================
7225 *
7226 * COLOR
7227 *
7228 * ===============================================================*/
7229NK_INTERN int
7230nk_parse_hex(const char *p, int length)
7231{
7232 int i = 0;
7233 int len = 0;
7234 while (len < length) {
7235 i <<= 4;
7236 if (p[len] >= 'a' && p[len] <= 'f')
7237 i += ((p[len] - 'a') + 10);
7238 else if (p[len] >= 'A' && p[len] <= 'F')
7239 i += ((p[len] - 'A') + 10);
7240 else i += (p[len] - '0');
7241 len++;
7242 }
7243 return i;
7244}
7245NK_API struct nk_color
7246nk_rgba(int r, int g, int b, int a)
7247{
7248 struct nk_color ret;
7249 ret.r = (nk_byte)NK_CLAMP(0, r, 255);
7250 ret.g = (nk_byte)NK_CLAMP(0, g, 255);
7251 ret.b = (nk_byte)NK_CLAMP(0, b, 255);
7252 ret.a = (nk_byte)NK_CLAMP(0, a, 255);
7253 return ret;
7254}
7255NK_API struct nk_color
7256nk_rgb_hex(const char *rgb)
7257{
7258 struct nk_color col;
7259 const char *c = rgb;
7260 if (*c == '#') c++;
7261 col.r = (nk_byte)nk_parse_hex(c, 2);
7262 col.g = (nk_byte)nk_parse_hex(c+2, 2);
7263 col.b = (nk_byte)nk_parse_hex(c+4, 2);
7264 col.a = 255;
7265 return col;
7266}
7267NK_API struct nk_color
7268nk_rgba_hex(const char *rgb)
7269{
7270 struct nk_color col;
7271 const char *c = rgb;
7272 if (*c == '#') c++;
7273 col.r = (nk_byte)nk_parse_hex(c, 2);
7274 col.g = (nk_byte)nk_parse_hex(c+2, 2);
7275 col.b = (nk_byte)nk_parse_hex(c+4, 2);
7276 col.a = (nk_byte)nk_parse_hex(c+6, 2);
7277 return col;
7278}
7279NK_API void
7280nk_color_hex_rgba(char *output, struct nk_color col)
7281{
7282 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
7283 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
7284 output[1] = (char)NK_TO_HEX((col.r & 0x0F));
7285 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
7286 output[3] = (char)NK_TO_HEX((col.g & 0x0F));
7287 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
7288 output[5] = (char)NK_TO_HEX((col.b & 0x0F));
7289 output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
7290 output[7] = (char)NK_TO_HEX((col.a & 0x0F));
7291 output[8] = '\0';
7292 #undef NK_TO_HEX
7293}
7294NK_API void
7295nk_color_hex_rgb(char *output, struct nk_color col)
7296{
7297 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
7298 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
7299 output[1] = (char)NK_TO_HEX((col.r & 0x0F));
7300 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
7301 output[3] = (char)NK_TO_HEX((col.g & 0x0F));
7302 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
7303 output[5] = (char)NK_TO_HEX((col.b & 0x0F));
7304 output[6] = '\0';
7305 #undef NK_TO_HEX
7306}
7307NK_API struct nk_color
7308nk_rgba_iv(const int *c)
7309{
7310 return nk_rgba(c[0], c[1], c[2], c[3]);
7311}
7312NK_API struct nk_color
7313nk_rgba_bv(const nk_byte *c)
7314{
7315 return nk_rgba(c[0], c[1], c[2], c[3]);
7316}
7317NK_API struct nk_color
7318nk_rgb(int r, int g, int b)
7319{
7320 struct nk_color ret;
7321 ret.r = (nk_byte)NK_CLAMP(0, r, 255);
7322 ret.g = (nk_byte)NK_CLAMP(0, g, 255);
7323 ret.b = (nk_byte)NK_CLAMP(0, b, 255);
7324 ret.a = (nk_byte)255;
7325 return ret;
7326}
7327NK_API struct nk_color
7328nk_rgb_iv(const int *c)
7329{
7330 return nk_rgb(c[0], c[1], c[2]);
7331}
7332NK_API struct nk_color
7333nk_rgb_bv(const nk_byte* c)
7334{
7335 return nk_rgb(c[0], c[1], c[2]);
7336}
7337NK_API struct nk_color
7339{
7340 struct nk_color ret;
7341 ret.r = (in & 0xFF);
7342 ret.g = ((in >> 8) & 0xFF);
7343 ret.b = ((in >> 16) & 0xFF);
7344 ret.a = (nk_byte)((in >> 24) & 0xFF);
7345 return ret;
7346}
7347NK_API struct nk_color
7348nk_rgba_f(float r, float g, float b, float a)
7349{
7350 struct nk_color ret;
7351 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
7352 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
7353 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
7354 ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
7355 return ret;
7356}
7357NK_API struct nk_color
7358nk_rgba_fv(const float *c)
7359{
7360 return nk_rgba_f(c[0], c[1], c[2], c[3]);
7361}
7362NK_API struct nk_color
7363nk_rgba_cf(struct nk_colorf c)
7364{
7365 return nk_rgba_f(c.r, c.g, c.b, c.a);
7366}
7367NK_API struct nk_color
7368nk_rgb_f(float r, float g, float b)
7369{
7370 struct nk_color ret;
7371 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
7372 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
7373 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
7374 ret.a = 255;
7375 return ret;
7376}
7377NK_API struct nk_color
7378nk_rgb_fv(const float *c)
7379{
7380 return nk_rgb_f(c[0], c[1], c[2]);
7381}
7382NK_API struct nk_color
7383nk_rgb_cf(struct nk_colorf c)
7384{
7385 return nk_rgb_f(c.r, c.g, c.b);
7386}
7387NK_API struct nk_color
7388nk_hsv(int h, int s, int v)
7389{
7390 return nk_hsva(h, s, v, 255);
7391}
7392NK_API struct nk_color
7393nk_hsv_iv(const int *c)
7394{
7395 return nk_hsv(c[0], c[1], c[2]);
7396}
7397NK_API struct nk_color
7398nk_hsv_bv(const nk_byte *c)
7399{
7400 return nk_hsv(c[0], c[1], c[2]);
7401}
7402NK_API struct nk_color
7403nk_hsv_f(float h, float s, float v)
7404{
7405 return nk_hsva_f(h, s, v, 1.0f);
7406}
7407NK_API struct nk_color
7408nk_hsv_fv(const float *c)
7409{
7410 return nk_hsv_f(c[0], c[1], c[2]);
7411}
7412NK_API struct nk_color
7413nk_hsva(int h, int s, int v, int a)
7414{
7415 float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
7416 float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
7417 float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
7418 float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
7419 return nk_hsva_f(hf, sf, vf, af);
7420}
7421NK_API struct nk_color
7422nk_hsva_iv(const int *c)
7423{
7424 return nk_hsva(c[0], c[1], c[2], c[3]);
7425}
7426NK_API struct nk_color
7427nk_hsva_bv(const nk_byte *c)
7428{
7429 return nk_hsva(c[0], c[1], c[2], c[3]);
7430}
7431NK_API struct nk_colorf
7432nk_hsva_colorf(float h, float s, float v, float a)
7433{
7434 int i;
7435 float p, q, t, f;
7436 struct nk_colorf out = {0,0,0,0};
7437 if (s <= 0.0f) {
7438 out.r = v; out.g = v; out.b = v; out.a = a;
7439 return out;
7440 }
7441 h = h / (60.0f/360.0f);
7442 i = (int)h;
7443 f = h - (float)i;
7444 p = v * (1.0f - s);
7445 q = v * (1.0f - (s * f));
7446 t = v * (1.0f - s * (1.0f - f));
7447
7448 switch (i) {
7449 case 0: default: out.r = v; out.g = t; out.b = p; break;
7450 case 1: out.r = q; out.g = v; out.b = p; break;
7451 case 2: out.r = p; out.g = v; out.b = t; break;
7452 case 3: out.r = p; out.g = q; out.b = v; break;
7453 case 4: out.r = t; out.g = p; out.b = v; break;
7454 case 5: out.r = v; out.g = p; out.b = q; break;}
7455 out.a = a;
7456 return out;
7457}
7458NK_API struct nk_colorf
7459nk_hsva_colorfv(float *c)
7460{
7461 return nk_hsva_colorf(c[0], c[1], c[2], c[3]);
7462}
7463NK_API struct nk_color
7464nk_hsva_f(float h, float s, float v, float a)
7465{
7466 struct nk_colorf c = nk_hsva_colorf(h, s, v, a);
7467 return nk_rgba_f(c.r, c.g, c.b, c.a);
7468}
7469NK_API struct nk_color
7470nk_hsva_fv(const float *c)
7471{
7472 return nk_hsva_f(c[0], c[1], c[2], c[3]);
7473}
7475nk_color_u32(struct nk_color in)
7476{
7477 nk_uint out = (nk_uint)in.r;
7478 out |= ((nk_uint)in.g << 8);
7479 out |= ((nk_uint)in.b << 16);
7480 out |= ((nk_uint)in.a << 24);
7481 return out;
7482}
7483NK_API void
7484nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
7485{
7486 NK_STORAGE const float s = 1.0f/255.0f;
7487 *r = (float)in.r * s;
7488 *g = (float)in.g * s;
7489 *b = (float)in.b * s;
7490 *a = (float)in.a * s;
7491}
7492NK_API void
7493nk_color_fv(float *c, struct nk_color in)
7494{
7495 nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
7496}
7497NK_API struct nk_colorf
7498nk_color_cf(struct nk_color in)
7499{
7500 struct nk_colorf o;
7501 nk_color_f(&o.r, &o.g, &o.b, &o.a, in);
7502 return o;
7503}
7504NK_API void
7505nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
7506{
7507 NK_STORAGE const double s = 1.0/255.0;
7508 *r = (double)in.r * s;
7509 *g = (double)in.g * s;
7510 *b = (double)in.b * s;
7511 *a = (double)in.a * s;
7512}
7513NK_API void
7514nk_color_dv(double *c, struct nk_color in)
7515{
7516 nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
7517}
7518NK_API void
7519nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
7520{
7521 float a;
7522 nk_color_hsva_f(out_h, out_s, out_v, &a, in);
7523}
7524NK_API void
7525nk_color_hsv_fv(float *out, struct nk_color in)
7526{
7527 float a;
7528 nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
7529}
7530NK_API void
7531nk_colorf_hsva_f(float *out_h, float *out_s,
7532 float *out_v, float *out_a, struct nk_colorf in)
7533{
7534 float chroma;
7535 float K = 0.0f;
7536 if (in.g < in.b) {
7537 const float t = in.g; in.g = in.b; in.b = t;
7538 K = -1.f;
7539 }
7540 if (in.r < in.g) {
7541 const float t = in.r; in.r = in.g; in.g = t;
7542 K = -2.f/6.0f - K;
7543 }
7544 chroma = in.r - ((in.g < in.b) ? in.g: in.b);
7545 *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f));
7546 *out_s = chroma / (in.r + 1e-20f);
7547 *out_v = in.r;
7548 *out_a = in.a;
7549
7550}
7551NK_API void
7552nk_colorf_hsva_fv(float *hsva, struct nk_colorf in)
7553{
7554 nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in);
7555}
7556NK_API void
7557nk_color_hsva_f(float *out_h, float *out_s,
7558 float *out_v, float *out_a, struct nk_color in)
7559{
7560 struct nk_colorf col;
7561 nk_color_f(&col.r,&col.g,&col.b,&col.a, in);
7562 nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col);
7563}
7564NK_API void
7565nk_color_hsva_fv(float *out, struct nk_color in)
7566{
7567 nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
7568}
7569NK_API void
7570nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
7571 int *out_a, struct nk_color in)
7572{
7573 float h,s,v,a;
7574 nk_color_hsva_f(&h, &s, &v, &a, in);
7575 *out_h = (nk_byte)(h * 255.0f);
7576 *out_s = (nk_byte)(s * 255.0f);
7577 *out_v = (nk_byte)(v * 255.0f);
7578 *out_a = (nk_byte)(a * 255.0f);
7579}
7580NK_API void
7581nk_color_hsva_iv(int *out, struct nk_color in)
7582{
7583 nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
7584}
7585NK_API void
7586nk_color_hsva_bv(nk_byte *out, struct nk_color in)
7587{
7588 int tmp[4];
7589 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7590 out[0] = (nk_byte)tmp[0];
7591 out[1] = (nk_byte)tmp[1];
7592 out[2] = (nk_byte)tmp[2];
7593 out[3] = (nk_byte)tmp[3];
7594}
7595NK_API void
7596nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
7597{
7598 int tmp[4];
7599 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7600 *h = (nk_byte)tmp[0];
7601 *s = (nk_byte)tmp[1];
7602 *v = (nk_byte)tmp[2];
7603 *a = (nk_byte)tmp[3];
7604}
7605NK_API void
7606nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
7607{
7608 int a;
7609 nk_color_hsva_i(out_h, out_s, out_v, &a, in);
7610}
7611NK_API void
7612nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
7613{
7614 int tmp[4];
7615 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7616 *out_h = (nk_byte)tmp[0];
7617 *out_s = (nk_byte)tmp[1];
7618 *out_v = (nk_byte)tmp[2];
7619}
7620NK_API void
7621nk_color_hsv_iv(int *out, struct nk_color in)
7622{
7623 nk_color_hsv_i(&out[0], &out[1], &out[2], in);
7624}
7625NK_API void
7626nk_color_hsv_bv(nk_byte *out, struct nk_color in)
7627{
7628 int tmp[4];
7629 nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
7630 out[0] = (nk_byte)tmp[0];
7631 out[1] = (nk_byte)tmp[1];
7632 out[2] = (nk_byte)tmp[2];
7633}
7634
7635
7636
7637
7638/* ===============================================================
7639 *
7640 * UTF-8
7641 *
7642 * ===============================================================*/
7643NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
7644NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
7645NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
7646NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
7647
7648NK_INTERN int
7649nk_utf_validate(nk_rune *u, int i)
7650{
7651 NK_ASSERT(u);
7652 if (!u) return 0;
7653 if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
7654 NK_BETWEEN(*u, 0xD800, 0xDFFF))
7655 *u = NK_UTF_INVALID;
7656 for (i = 1; *u > nk_utfmax[i]; ++i);
7657 return i;
7658}
7660nk_utf_decode_byte(char c, int *i)
7661{
7662 NK_ASSERT(i);
7663 if (!i) return 0;
7664 for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
7665 if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
7666 return (nk_byte)(c & ~nk_utfmask[*i]);
7667 }
7668 return 0;
7669}
7670NK_API int
7671nk_utf_decode(const char *c, nk_rune *u, int clen)
7672{
7673 int i, j, len, type=0;
7674 nk_rune udecoded;
7675
7676 NK_ASSERT(c);
7677 NK_ASSERT(u);
7678
7679 if (!c || !u) return 0;
7680 if (!clen) return 0;
7681 *u = NK_UTF_INVALID;
7682
7683 udecoded = nk_utf_decode_byte(c[0], &len);
7684 if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
7685 return 1;
7686
7687 for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
7688 udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
7689 if (type != 0)
7690 return j;
7691 }
7692 if (j < len)
7693 return 0;
7694 *u = udecoded;
7695 nk_utf_validate(u, len);
7696 return len;
7697}
7698NK_INTERN char
7699nk_utf_encode_byte(nk_rune u, int i)
7700{
7701 return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
7702}
7703NK_API int
7704nk_utf_encode(nk_rune u, char *c, int clen)
7705{
7706 int len, i;
7707 len = nk_utf_validate(&u, 0);
7708 if (clen < len || !len || len > NK_UTF_SIZE)
7709 return 0;
7710
7711 for (i = len - 1; i != 0; --i) {
7712 c[i] = nk_utf_encode_byte(u, 0);
7713 u >>= 6;
7714 }
7715 c[0] = nk_utf_encode_byte(u, len);
7716 return len;
7717}
7718NK_API int
7719nk_utf_len(const char *str, int len)
7720{
7721 const char *text;
7722 int glyphs = 0;
7723 int text_len;
7724 int glyph_len;
7725 int src_len = 0;
7726 nk_rune unicode;
7727
7728 NK_ASSERT(str);
7729 if (!str || !len) return 0;
7730
7731 text = str;
7732 text_len = len;
7733 glyph_len = nk_utf_decode(text, &unicode, text_len);
7734 while (glyph_len && src_len < len) {
7735 glyphs++;
7736 src_len = src_len + glyph_len;
7737 glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
7738 }
7739 return glyphs;
7740}
7741NK_API const char*
7742nk_utf_at(const char *buffer, int length, int index,
7743 nk_rune *unicode, int *len)
7744{
7745 int i = 0;
7746 int src_len = 0;
7747 int glyph_len = 0;
7748 const char *text;
7749 int text_len;
7750
7751 NK_ASSERT(buffer);
7752 NK_ASSERT(unicode);
7753 NK_ASSERT(len);
7754
7755 if (!buffer || !unicode || !len) return 0;
7756 if (index < 0) {
7757 *unicode = NK_UTF_INVALID;
7758 *len = 0;
7759 return 0;
7760 }
7761
7762 text = buffer;
7763 text_len = length;
7764 glyph_len = nk_utf_decode(text, unicode, text_len);
7765 while (glyph_len) {
7766 if (i == index) {
7767 *len = glyph_len;
7768 break;
7769 }
7770
7771 i++;
7772 src_len = src_len + glyph_len;
7773 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7774 }
7775 if (i != index) return 0;
7776 return buffer + src_len;
7777}
7778
7779
7780
7781
7782/* ==============================================================
7783 *
7784 * BUFFER
7785 *
7786 * ===============================================================*/
7787#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
7788NK_LIB void*
7789nk_malloc(nk_handle unused, void *old,nk_size size)
7790{
7791 NK_UNUSED(unused);
7792 NK_UNUSED(old);
7793 return malloc(size);
7794}
7795NK_LIB void
7796nk_mfree(nk_handle unused, void *ptr)
7797{
7798 NK_UNUSED(unused);
7799 free(ptr);
7800}
7801NK_API void
7802nk_buffer_init_default(struct nk_buffer *buffer)
7803{
7804 struct nk_allocator alloc;
7805 alloc.userdata.ptr = 0;
7806 alloc.alloc = nk_malloc;
7807 alloc.free = nk_mfree;
7808 nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
7809}
7810#endif
7811
7812NK_API void
7813nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
7814 nk_size initial_size)
7815{
7816 NK_ASSERT(b);
7817 NK_ASSERT(a);
7818 NK_ASSERT(initial_size);
7819 if (!b || !a || !initial_size) return;
7820
7821 nk_zero(b, sizeof(*b));
7823 b->memory.ptr = a->alloc(a->userdata,0, initial_size);
7824 b->memory.size = initial_size;
7825 b->size = initial_size;
7826 b->grow_factor = 2.0f;
7827 b->pool = *a;
7828}
7829NK_API void
7830nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
7831{
7832 NK_ASSERT(b);
7833 NK_ASSERT(m);
7834 NK_ASSERT(size);
7835 if (!b || !m || !size) return;
7836
7837 nk_zero(b, sizeof(*b));
7838 b->type = NK_BUFFER_FIXED;
7839 b->memory.ptr = m;
7840 b->memory.size = size;
7841 b->size = size;
7842}
7843NK_LIB void*
7844nk_buffer_align(void *unaligned,
7845 nk_size align, nk_size *alignment,
7846 enum nk_buffer_allocation_type type)
7847{
7848 void *memory = 0;
7849 switch (type) {
7850 default:
7851 case NK_BUFFER_MAX:
7852 case NK_BUFFER_FRONT:
7853 if (align) {
7854 memory = NK_ALIGN_PTR(unaligned, align);
7855 *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
7856 } else {
7857 memory = unaligned;
7858 *alignment = 0;
7859 }
7860 break;
7861 case NK_BUFFER_BACK:
7862 if (align) {
7863 memory = NK_ALIGN_PTR_BACK(unaligned, align);
7864 *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
7865 } else {
7866 memory = unaligned;
7867 *alignment = 0;
7868 }
7869 break;
7870 }
7871 return memory;
7872}
7873NK_LIB void*
7874nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
7875{
7876 void *temp;
7877 nk_size buffer_size;
7878
7879 NK_ASSERT(b);
7880 NK_ASSERT(size);
7881 if (!b || !size || !b->pool.alloc || !b->pool.free)
7882 return 0;
7883
7884 buffer_size = b->memory.size;
7885 temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
7886 NK_ASSERT(temp);
7887 if (!temp) return 0;
7888
7889 *size = capacity;
7890 if (temp != b->memory.ptr) {
7891 NK_MEMCPY(temp, b->memory.ptr, buffer_size);
7892 b->pool.free(b->pool.userdata, b->memory.ptr);
7893 }
7894
7895 if (b->size == buffer_size) {
7896 /* no back buffer so just set correct size */
7897 b->size = capacity;
7898 return temp;
7899 } else {
7900 /* copy back buffer to the end of the new buffer */
7901 void *dst, *src;
7902 nk_size back_size;
7903 back_size = buffer_size - b->size;
7904 dst = nk_ptr_add(void, temp, capacity - back_size);
7905 src = nk_ptr_add(void, temp, b->size);
7906 NK_MEMCPY(dst, src, back_size);
7907 b->size = capacity - back_size;
7908 }
7909 return temp;
7910}
7911NK_LIB void*
7912nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
7913 nk_size size, nk_size align)
7914{
7915 int full;
7916 nk_size alignment;
7917 void *unaligned;
7918 void *memory;
7919
7920 NK_ASSERT(b);
7921 NK_ASSERT(size);
7922 if (!b || !size) return 0;
7923 b->needed += size;
7924
7925 /* calculate total size with needed alignment + size */
7926 if (type == NK_BUFFER_FRONT)
7927 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
7928 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
7929 memory = nk_buffer_align(unaligned, align, &alignment, type);
7930
7931 /* check if buffer has enough memory*/
7932 if (type == NK_BUFFER_FRONT)
7933 full = ((b->allocated + size + alignment) > b->size);
7934 else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
7935
7936 if (full) {
7937 nk_size capacity;
7938 if (b->type != NK_BUFFER_DYNAMIC)
7939 return 0;
7940 NK_ASSERT(b->pool.alloc && b->pool.free);
7941 if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
7942 return 0;
7943
7944 /* buffer is full so allocate bigger buffer if dynamic */
7945 capacity = (nk_size)((float)b->memory.size * b->grow_factor);
7946 capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
7947 b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
7948 if (!b->memory.ptr) return 0;
7949
7950 /* align newly allocated pointer */
7951 if (type == NK_BUFFER_FRONT)
7952 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
7953 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
7954 memory = nk_buffer_align(unaligned, align, &alignment, type);
7955 }
7956 if (type == NK_BUFFER_FRONT)
7957 b->allocated += size + alignment;
7958 else b->size -= (size + alignment);
7959 b->needed += alignment;
7960 b->calls++;
7961 return memory;
7962}
7963NK_API void
7965 const void *memory, nk_size size, nk_size align)
7966{
7967 void *mem = nk_buffer_alloc(b, type, size, align);
7968 if (!mem) return;
7969 NK_MEMCPY(mem, memory, size);
7970}
7971NK_API void
7972nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
7973{
7974 NK_ASSERT(buffer);
7975 if (!buffer) return;
7976 buffer->marker[type].active = nk_true;
7977 if (type == NK_BUFFER_BACK)
7978 buffer->marker[type].offset = buffer->size;
7979 else buffer->marker[type].offset = buffer->allocated;
7980}
7981NK_API void
7982nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
7983{
7984 NK_ASSERT(buffer);
7985 if (!buffer) return;
7986 if (type == NK_BUFFER_BACK) {
7987 /* reset back buffer either back to marker or empty */
7988 buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
7989 if (buffer->marker[type].active)
7990 buffer->size = buffer->marker[type].offset;
7991 else buffer->size = buffer->memory.size;
7992 buffer->marker[type].active = nk_false;
7993 } else {
7994 /* reset front buffer either back to back marker or empty */
7995 buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
7996 if (buffer->marker[type].active)
7997 buffer->allocated = buffer->marker[type].offset;
7998 else buffer->allocated = 0;
7999 buffer->marker[type].active = nk_false;
8000 }
8001}
8002NK_API void
8003nk_buffer_clear(struct nk_buffer *b)
8004{
8005 NK_ASSERT(b);
8006 if (!b) return;
8007 b->allocated = 0;
8008 b->size = b->memory.size;
8009 b->calls = 0;
8010 b->needed = 0;
8011}
8012NK_API void
8013nk_buffer_free(struct nk_buffer *b)
8014{
8015 NK_ASSERT(b);
8016 if (!b || !b->memory.ptr) return;
8017 if (b->type == NK_BUFFER_FIXED) return;
8018 if (!b->pool.free) return;
8019 NK_ASSERT(b->pool.free);
8020 b->pool.free(b->pool.userdata, b->memory.ptr);
8021}
8022NK_API void
8023nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
8024{
8025 NK_ASSERT(b);
8026 NK_ASSERT(s);
8027 if (!s || !b) return;
8028 s->allocated = b->allocated;
8029 s->size = b->memory.size;
8030 s->needed = b->needed;
8031 s->memory = b->memory.ptr;
8032 s->calls = b->calls;
8033}
8034NK_API void*
8035nk_buffer_memory(struct nk_buffer *buffer)
8036{
8037 NK_ASSERT(buffer);
8038 if (!buffer) return 0;
8039 return buffer->memory.ptr;
8040}
8041NK_API const void*
8042nk_buffer_memory_const(const struct nk_buffer *buffer)
8043{
8044 NK_ASSERT(buffer);
8045 if (!buffer) return 0;
8046 return buffer->memory.ptr;
8047}
8049nk_buffer_total(struct nk_buffer *buffer)
8050{
8051 NK_ASSERT(buffer);
8052 if (!buffer) return 0;
8053 return buffer->memory.size;
8054}
8055
8056
8057
8058
8059/* ===============================================================
8060 *
8061 * STRING
8062 *
8063 * ===============================================================*/
8064#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
8065NK_API void
8066nk_str_init_default(struct nk_str *str)
8067{
8068 struct nk_allocator alloc;
8069 alloc.userdata.ptr = 0;
8070 alloc.alloc = nk_malloc;
8071 alloc.free = nk_mfree;
8072 nk_buffer_init(&str->buffer, &alloc, 32);
8073 str->len = 0;
8074}
8075#endif
8076
8077NK_API void
8078nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
8079{
8080 nk_buffer_init(&str->buffer, alloc, size);
8081 str->len = 0;
8082}
8083NK_API void
8084nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
8085{
8086 nk_buffer_init_fixed(&str->buffer, memory, size);
8087 str->len = 0;
8088}
8089NK_API int
8090nk_str_append_text_char(struct nk_str *s, const char *str, int len)
8091{
8092 char *mem;
8093 NK_ASSERT(s);
8094 NK_ASSERT(str);
8095 if (!s || !str || !len) return 0;
8096 mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
8097 if (!mem) return 0;
8098 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
8099 s->len += nk_utf_len(str, len);
8100 return len;
8101}
8102NK_API int
8103nk_str_append_str_char(struct nk_str *s, const char *str)
8104{
8105 return nk_str_append_text_char(s, str, nk_strlen(str));
8106}
8107NK_API int
8108nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
8109{
8110 int i = 0;
8111 int byte_len = 0;
8112 nk_rune unicode;
8113 if (!str || !text || !len) return 0;
8114 for (i = 0; i < len; ++i)
8115 byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
8116 nk_str_append_text_char(str, text, byte_len);
8117 return len;
8118}
8119NK_API int
8120nk_str_append_str_utf8(struct nk_str *str, const char *text)
8121{
8122 int runes = 0;
8123 int byte_len = 0;
8124 int num_runes = 0;
8125 int glyph_len = 0;
8126 nk_rune unicode;
8127 if (!str || !text) return 0;
8128
8129 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
8130 while (unicode != '\0' && glyph_len) {
8131 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
8132 byte_len += glyph_len;
8133 num_runes++;
8134 }
8135 nk_str_append_text_char(str, text, byte_len);
8136 return runes;
8137}
8138NK_API int
8139nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
8140{
8141 int i = 0;
8142 int byte_len = 0;
8143 nk_glyph glyph;
8144
8145 NK_ASSERT(str);
8146 if (!str || !text || !len) return 0;
8147 for (i = 0; i < len; ++i) {
8148 byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
8149 if (!byte_len) break;
8150 nk_str_append_text_char(str, glyph, byte_len);
8151 }
8152 return len;
8153}
8154NK_API int
8155nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
8156{
8157 int i = 0;
8158 nk_glyph glyph;
8159 int byte_len;
8160 NK_ASSERT(str);
8161 if (!str || !runes) return 0;
8162 while (runes[i] != '\0') {
8163 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8164 nk_str_append_text_char(str, glyph, byte_len);
8165 i++;
8166 }
8167 return i;
8168}
8169NK_API int
8170nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
8171{
8172 int i;
8173 void *mem;
8174 char *src;
8175 char *dst;
8176
8177 int copylen;
8178 NK_ASSERT(s);
8179 NK_ASSERT(str);
8180 NK_ASSERT(len >= 0);
8181 if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
8182 if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
8183 (s->buffer.type == NK_BUFFER_FIXED)) return 0;
8184
8185 copylen = (int)s->buffer.allocated - pos;
8186 if (!copylen) {
8187 nk_str_append_text_char(s, str, len);
8188 return 1;
8189 }
8190 mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
8191 if (!mem) return 0;
8192
8193 /* memmove */
8194 NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
8195 NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
8196 dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
8197 src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
8198 for (i = 0; i < copylen; ++i) *dst-- = *src--;
8199 mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
8200 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
8201 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8202 return 1;
8203}
8204NK_API int
8205nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
8206{
8207 int glyph_len;
8208 nk_rune unicode;
8209 const char *begin;
8210 const char *buffer;
8211
8212 NK_ASSERT(str);
8213 NK_ASSERT(cstr);
8214 NK_ASSERT(len);
8215 if (!str || !cstr || !len) return 0;
8216 begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
8217 if (!str->len)
8218 return nk_str_append_text_char(str, cstr, len);
8219 buffer = nk_str_get_const(str);
8220 if (!begin) return 0;
8221 return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
8222}
8223NK_API int
8224nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
8225{
8226 return nk_str_insert_text_utf8(str, pos, text, len);
8227}
8228NK_API int
8229nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
8230{
8231 return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
8232}
8233NK_API int
8234nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
8235{
8236 int i = 0;
8237 int byte_len = 0;
8238 nk_rune unicode;
8239
8240 NK_ASSERT(str);
8241 NK_ASSERT(text);
8242 if (!str || !text || !len) return 0;
8243 for (i = 0; i < len; ++i)
8244 byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
8245 nk_str_insert_at_rune(str, pos, text, byte_len);
8246 return len;
8247}
8248NK_API int
8249nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
8250{
8251 int runes = 0;
8252 int byte_len = 0;
8253 int num_runes = 0;
8254 int glyph_len = 0;
8255 nk_rune unicode;
8256 if (!str || !text) return 0;
8257
8258 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
8259 while (unicode != '\0' && glyph_len) {
8260 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
8261 byte_len += glyph_len;
8262 num_runes++;
8263 }
8264 nk_str_insert_at_rune(str, pos, text, byte_len);
8265 return runes;
8266}
8267NK_API int
8268nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
8269{
8270 int i = 0;
8271 int byte_len = 0;
8272 nk_glyph glyph;
8273
8274 NK_ASSERT(str);
8275 if (!str || !runes || !len) return 0;
8276 for (i = 0; i < len; ++i) {
8277 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8278 if (!byte_len) break;
8279 nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
8280 }
8281 return len;
8282}
8283NK_API int
8284nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
8285{
8286 int i = 0;
8287 nk_glyph glyph;
8288 int byte_len;
8289 NK_ASSERT(str);
8290 if (!str || !runes) return 0;
8291 while (runes[i] != '\0') {
8292 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8293 nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
8294 i++;
8295 }
8296 return i;
8297}
8298NK_API void
8299nk_str_remove_chars(struct nk_str *s, int len)
8300{
8301 NK_ASSERT(s);
8302 NK_ASSERT(len >= 0);
8303 if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
8304 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
8305 s->buffer.allocated -= (nk_size)len;
8306 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8307}
8308NK_API void
8309nk_str_remove_runes(struct nk_str *str, int len)
8310{
8311 int index;
8312 const char *begin;
8313 const char *end;
8314 nk_rune unicode;
8315
8316 NK_ASSERT(str);
8317 NK_ASSERT(len >= 0);
8318 if (!str || len < 0) return;
8319 if (len >= str->len) {
8320 str->len = 0;
8321 return;
8322 }
8323
8324 index = str->len - len;
8325 begin = nk_str_at_rune(str, index, &unicode, &len);
8326 end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
8327 nk_str_remove_chars(str, (int)(end-begin)+1);
8328}
8329NK_API void
8330nk_str_delete_chars(struct nk_str *s, int pos, int len)
8331{
8332 NK_ASSERT(s);
8333 if (!s || !len || (nk_size)pos > s->buffer.allocated ||
8334 (nk_size)(pos + len) > s->buffer.allocated) return;
8335
8336 if ((nk_size)(pos + len) < s->buffer.allocated) {
8337 /* memmove */
8338 char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
8339 char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
8340 NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
8341 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
8342 s->buffer.allocated -= (nk_size)len;
8343 } else nk_str_remove_chars(s, len);
8344 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8345}
8346NK_API void
8347nk_str_delete_runes(struct nk_str *s, int pos, int len)
8348{
8349 char *temp;
8350 nk_rune unicode;
8351 char *begin;
8352 char *end;
8353 int unused;
8354
8355 NK_ASSERT(s);
8356 NK_ASSERT(s->len >= pos + len);
8357 if (s->len < pos + len)
8358 len = NK_CLAMP(0, (s->len - pos), s->len);
8359 if (!len) return;
8360
8361 temp = (char *)s->buffer.memory.ptr;
8362 begin = nk_str_at_rune(s, pos, &unicode, &unused);
8363 if (!begin) return;
8364 s->buffer.memory.ptr = begin;
8365 end = nk_str_at_rune(s, len, &unicode, &unused);
8366 s->buffer.memory.ptr = temp;
8367 if (!end) return;
8368 nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
8369}
8370NK_API char*
8371nk_str_at_char(struct nk_str *s, int pos)
8372{
8373 NK_ASSERT(s);
8374 if (!s || pos > (int)s->buffer.allocated) return 0;
8375 return nk_ptr_add(char, s->buffer.memory.ptr, pos);
8376}
8377NK_API char*
8378nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
8379{
8380 int i = 0;
8381 int src_len = 0;
8382 int glyph_len = 0;
8383 char *text;
8384 int text_len;
8385
8386 NK_ASSERT(str);
8387 NK_ASSERT(unicode);
8388 NK_ASSERT(len);
8389
8390 if (!str || !unicode || !len) return 0;
8391 if (pos < 0) {
8392 *unicode = 0;
8393 *len = 0;
8394 return 0;
8395 }
8396
8397 text = (char*)str->buffer.memory.ptr;
8398 text_len = (int)str->buffer.allocated;
8399 glyph_len = nk_utf_decode(text, unicode, text_len);
8400 while (glyph_len) {
8401 if (i == pos) {
8402 *len = glyph_len;
8403 break;
8404 }
8405
8406 i++;
8407 src_len = src_len + glyph_len;
8408 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
8409 }
8410 if (i != pos) return 0;
8411 return text + src_len;
8412}
8413NK_API const char*
8414nk_str_at_char_const(const struct nk_str *s, int pos)
8415{
8416 NK_ASSERT(s);
8417 if (!s || pos > (int)s->buffer.allocated) return 0;
8418 return nk_ptr_add(char, s->buffer.memory.ptr, pos);
8419}
8420NK_API const char*
8421nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
8422{
8423 int i = 0;
8424 int src_len = 0;
8425 int glyph_len = 0;
8426 char *text;
8427 int text_len;
8428
8429 NK_ASSERT(str);
8430 NK_ASSERT(unicode);
8431 NK_ASSERT(len);
8432
8433 if (!str || !unicode || !len) return 0;
8434 if (pos < 0) {
8435 *unicode = 0;
8436 *len = 0;
8437 return 0;
8438 }
8439
8440 text = (char*)str->buffer.memory.ptr;
8441 text_len = (int)str->buffer.allocated;
8442 glyph_len = nk_utf_decode(text, unicode, text_len);
8443 while (glyph_len) {
8444 if (i == pos) {
8445 *len = glyph_len;
8446 break;
8447 }
8448
8449 i++;
8450 src_len = src_len + glyph_len;
8451 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
8452 }
8453 if (i != pos) return 0;
8454 return text + src_len;
8455}
8457nk_str_rune_at(const struct nk_str *str, int pos)
8458{
8459 int len;
8460 nk_rune unicode = 0;
8461 nk_str_at_const(str, pos, &unicode, &len);
8462 return unicode;
8463}
8464NK_API char*
8465nk_str_get(struct nk_str *s)
8466{
8467 NK_ASSERT(s);
8468 if (!s || !s->len || !s->buffer.allocated) return 0;
8469 return (char*)s->buffer.memory.ptr;
8470}
8471NK_API const char*
8472nk_str_get_const(const struct nk_str *s)
8473{
8474 NK_ASSERT(s);
8475 if (!s || !s->len || !s->buffer.allocated) return 0;
8476 return (const char*)s->buffer.memory.ptr;
8477}
8478NK_API int
8479nk_str_len(struct nk_str *s)
8480{
8481 NK_ASSERT(s);
8482 if (!s || !s->len || !s->buffer.allocated) return 0;
8483 return s->len;
8484}
8485NK_API int
8486nk_str_len_char(struct nk_str *s)
8487{
8488 NK_ASSERT(s);
8489 if (!s || !s->len || !s->buffer.allocated) return 0;
8490 return (int)s->buffer.allocated;
8491}
8492NK_API void
8493nk_str_clear(struct nk_str *str)
8494{
8495 NK_ASSERT(str);
8496 nk_buffer_clear(&str->buffer);
8497 str->len = 0;
8498}
8499NK_API void
8500nk_str_free(struct nk_str *str)
8501{
8502 NK_ASSERT(str);
8503 nk_buffer_free(&str->buffer);
8504 str->len = 0;
8505}
8506
8507
8508
8509
8510/* ==============================================================
8511 *
8512 * DRAW
8513 *
8514 * ===============================================================*/
8515NK_LIB void
8516nk_command_buffer_init(struct nk_command_buffer *cb,
8517 struct nk_buffer *b, enum nk_command_clipping clip)
8518{
8519 NK_ASSERT(cb);
8520 NK_ASSERT(b);
8521 if (!cb || !b) return;
8522 cb->base = b;
8523 cb->use_clipping = (int)clip;
8524 cb->begin = b->allocated;
8525 cb->end = b->allocated;
8526 cb->last = b->allocated;
8527}
8528NK_LIB void
8529nk_command_buffer_reset(struct nk_command_buffer *b)
8530{
8531 NK_ASSERT(b);
8532 if (!b) return;
8533 b->begin = 0;
8534 b->end = 0;
8535 b->last = 0;
8536 b->clip = nk_null_rect;
8537#ifdef NK_INCLUDE_COMMAND_USERDATA
8538 b->userdata.ptr = 0;
8539#endif
8540}
8541NK_LIB void*
8542nk_command_buffer_push(struct nk_command_buffer* b,
8543 enum nk_command_type t, nk_size size)
8544{
8545 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
8546 struct nk_command *cmd;
8547 nk_size alignment;
8548 void *unaligned;
8549 void *memory;
8550
8551 NK_ASSERT(b);
8552 NK_ASSERT(b->base);
8553 if (!b) return 0;
8554 cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
8555 if (!cmd) return 0;
8556
8557 /* make sure the offset to the next command is aligned */
8558 b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
8559 unaligned = (nk_byte*)cmd + size;
8560 memory = NK_ALIGN_PTR(unaligned, align);
8561 alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
8562#ifdef NK_ZERO_COMMAND_MEMORY
8563 NK_MEMSET(cmd, 0, size + alignment);
8564#endif
8565
8566 cmd->type = t;
8567 cmd->next = b->base->allocated + alignment;
8568#ifdef NK_INCLUDE_COMMAND_USERDATA
8569 cmd->userdata = b->userdata;
8570#endif
8571 b->end = cmd->next;
8572 return cmd;
8573}
8574NK_API void
8575nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
8576{
8577 struct nk_command_scissor *cmd;
8578 NK_ASSERT(b);
8579 if (!b) return;
8580
8581 b->clip.x = r.x;
8582 b->clip.y = r.y;
8583 b->clip.w = r.w;
8584 b->clip.h = r.h;
8585 cmd = (struct nk_command_scissor*)
8586 nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
8587
8588 if (!cmd) return;
8589 cmd->x = (short)r.x;
8590 cmd->y = (short)r.y;
8591 cmd->w = (unsigned short)NK_MAX(0, r.w);
8592 cmd->h = (unsigned short)NK_MAX(0, r.h);
8593}
8594NK_API void
8595nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
8596 float x1, float y1, float line_thickness, struct nk_color c)
8597{
8598 struct nk_command_line *cmd;
8599 NK_ASSERT(b);
8600 if (!b || line_thickness <= 0) return;
8601 cmd = (struct nk_command_line*)
8602 nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
8603 if (!cmd) return;
8604 cmd->line_thickness = (unsigned short)line_thickness;
8605 cmd->begin.x = (short)x0;
8606 cmd->begin.y = (short)y0;
8607 cmd->end.x = (short)x1;
8608 cmd->end.y = (short)y1;
8609 cmd->color = c;
8610}
8611NK_API void
8612nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
8613 float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
8614 float bx, float by, float line_thickness, struct nk_color col)
8615{
8616 struct nk_command_curve *cmd;
8617 NK_ASSERT(b);
8618 if (!b || col.a == 0 || line_thickness <= 0) return;
8619
8620 cmd = (struct nk_command_curve*)
8621 nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
8622 if (!cmd) return;
8623 cmd->line_thickness = (unsigned short)line_thickness;
8624 cmd->begin.x = (short)ax;
8625 cmd->begin.y = (short)ay;
8626 cmd->ctrl[0].x = (short)ctrl0x;
8627 cmd->ctrl[0].y = (short)ctrl0y;
8628 cmd->ctrl[1].x = (short)ctrl1x;
8629 cmd->ctrl[1].y = (short)ctrl1y;
8630 cmd->end.x = (short)bx;
8631 cmd->end.y = (short)by;
8632 cmd->color = col;
8633}
8634NK_API void
8635nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
8636 float rounding, float line_thickness, struct nk_color c)
8637{
8638 struct nk_command_rect *cmd;
8639 NK_ASSERT(b);
8640 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
8641 if (b->use_clipping) {
8642 const struct nk_rect *clip = &b->clip;
8643 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8644 clip->x, clip->y, clip->w, clip->h)) return;
8645 }
8646 cmd = (struct nk_command_rect*)
8647 nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
8648 if (!cmd) return;
8649 cmd->rounding = (unsigned short)rounding;
8650 cmd->line_thickness = (unsigned short)line_thickness;
8651 cmd->x = (short)rect.x;
8652 cmd->y = (short)rect.y;
8653 cmd->w = (unsigned short)NK_MAX(0, rect.w);
8654 cmd->h = (unsigned short)NK_MAX(0, rect.h);
8655 cmd->color = c;
8656}
8657NK_API void
8658nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
8659 float rounding, struct nk_color c)
8660{
8661 struct nk_command_rect_filled *cmd;
8662 NK_ASSERT(b);
8663 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
8664 if (b->use_clipping) {
8665 const struct nk_rect *clip = &b->clip;
8666 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8667 clip->x, clip->y, clip->w, clip->h)) return;
8668 }
8669
8670 cmd = (struct nk_command_rect_filled*)
8671 nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
8672 if (!cmd) return;
8673 cmd->rounding = (unsigned short)rounding;
8674 cmd->x = (short)rect.x;
8675 cmd->y = (short)rect.y;
8676 cmd->w = (unsigned short)NK_MAX(0, rect.w);
8677 cmd->h = (unsigned short)NK_MAX(0, rect.h);
8678 cmd->color = c;
8679}
8680NK_API void
8682 struct nk_color left, struct nk_color top, struct nk_color right,
8683 struct nk_color bottom)
8684{
8685 struct nk_command_rect_multi_color *cmd;
8686 NK_ASSERT(b);
8687 if (!b || rect.w == 0 || rect.h == 0) return;
8688 if (b->use_clipping) {
8689 const struct nk_rect *clip = &b->clip;
8690 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8691 clip->x, clip->y, clip->w, clip->h)) return;
8692 }
8693
8694 cmd = (struct nk_command_rect_multi_color*)
8695 nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
8696 if (!cmd) return;
8697 cmd->x = (short)rect.x;
8698 cmd->y = (short)rect.y;
8699 cmd->w = (unsigned short)NK_MAX(0, rect.w);
8700 cmd->h = (unsigned short)NK_MAX(0, rect.h);
8701 cmd->left = left;
8702 cmd->top = top;
8703 cmd->right = right;
8704 cmd->bottom = bottom;
8705}
8706NK_API void
8707nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
8708 float line_thickness, struct nk_color c)
8709{
8710 struct nk_command_circle *cmd;
8711 if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
8712 if (b->use_clipping) {
8713 const struct nk_rect *clip = &b->clip;
8714 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
8715 return;
8716 }
8717
8718 cmd = (struct nk_command_circle*)
8719 nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
8720 if (!cmd) return;
8721 cmd->line_thickness = (unsigned short)line_thickness;
8722 cmd->x = (short)r.x;
8723 cmd->y = (short)r.y;
8724 cmd->w = (unsigned short)NK_MAX(r.w, 0);
8725 cmd->h = (unsigned short)NK_MAX(r.h, 0);
8726 cmd->color = c;
8727}
8728NK_API void
8729nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
8730{
8731 struct nk_command_circle_filled *cmd;
8732 NK_ASSERT(b);
8733 if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
8734 if (b->use_clipping) {
8735 const struct nk_rect *clip = &b->clip;
8736 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
8737 return;
8738 }
8739
8740 cmd = (struct nk_command_circle_filled*)
8741 nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
8742 if (!cmd) return;
8743 cmd->x = (short)r.x;
8744 cmd->y = (short)r.y;
8745 cmd->w = (unsigned short)NK_MAX(r.w, 0);
8746 cmd->h = (unsigned short)NK_MAX(r.h, 0);
8747 cmd->color = c;
8748}
8749NK_API void
8750nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
8751 float a_min, float a_max, float line_thickness, struct nk_color c)
8752{
8753 struct nk_command_arc *cmd;
8754 if (!b || c.a == 0 || line_thickness <= 0) return;
8755 cmd = (struct nk_command_arc*)
8756 nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
8757 if (!cmd) return;
8758 cmd->line_thickness = (unsigned short)line_thickness;
8759 cmd->cx = (short)cx;
8760 cmd->cy = (short)cy;
8761 cmd->r = (unsigned short)radius;
8762 cmd->a[0] = a_min;
8763 cmd->a[1] = a_max;
8764 cmd->color = c;
8765}
8766NK_API void
8767nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
8768 float a_min, float a_max, struct nk_color c)
8769{
8770 struct nk_command_arc_filled *cmd;
8771 NK_ASSERT(b);
8772 if (!b || c.a == 0) return;
8773 cmd = (struct nk_command_arc_filled*)
8774 nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
8775 if (!cmd) return;
8776 cmd->cx = (short)cx;
8777 cmd->cy = (short)cy;
8778 cmd->r = (unsigned short)radius;
8779 cmd->a[0] = a_min;
8780 cmd->a[1] = a_max;
8781 cmd->color = c;
8782}
8783NK_API void
8784nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
8785 float y1, float x2, float y2, float line_thickness, struct nk_color c)
8786{
8787 struct nk_command_triangle *cmd;
8788 NK_ASSERT(b);
8789 if (!b || c.a == 0 || line_thickness <= 0) return;
8790 if (b->use_clipping) {
8791 const struct nk_rect *clip = &b->clip;
8792 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
8793 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
8794 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
8795 return;
8796 }
8797
8798 cmd = (struct nk_command_triangle*)
8799 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
8800 if (!cmd) return;
8801 cmd->line_thickness = (unsigned short)line_thickness;
8802 cmd->a.x = (short)x0;
8803 cmd->a.y = (short)y0;
8804 cmd->b.x = (short)x1;
8805 cmd->b.y = (short)y1;
8806 cmd->c.x = (short)x2;
8807 cmd->c.y = (short)y2;
8808 cmd->color = c;
8809}
8810NK_API void
8811nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
8812 float y1, float x2, float y2, struct nk_color c)
8813{
8814 struct nk_command_triangle_filled *cmd;
8815 NK_ASSERT(b);
8816 if (!b || c.a == 0) return;
8817 if (!b) return;
8818 if (b->use_clipping) {
8819 const struct nk_rect *clip = &b->clip;
8820 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
8821 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
8822 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
8823 return;
8824 }
8825
8826 cmd = (struct nk_command_triangle_filled*)
8827 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
8828 if (!cmd) return;
8829 cmd->a.x = (short)x0;
8830 cmd->a.y = (short)y0;
8831 cmd->b.x = (short)x1;
8832 cmd->b.y = (short)y1;
8833 cmd->c.x = (short)x2;
8834 cmd->c.y = (short)y2;
8835 cmd->color = c;
8836}
8837NK_API void
8838nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count,
8839 float line_thickness, struct nk_color col)
8840{
8841 int i;
8842 nk_size size = 0;
8843 struct nk_command_polygon *cmd;
8844
8845 NK_ASSERT(b);
8846 if (!b || col.a == 0 || line_thickness <= 0) return;
8847 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
8848 cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
8849 if (!cmd) return;
8850 cmd->color = col;
8851 cmd->line_thickness = (unsigned short)line_thickness;
8852 cmd->point_count = (unsigned short)point_count;
8853 for (i = 0; i < point_count; ++i) {
8854 cmd->points[i].x = (short)points[i*2];
8855 cmd->points[i].y = (short)points[i*2+1];
8856 }
8857}
8858NK_API void
8860 struct nk_color col)
8861{
8862 int i;
8863 nk_size size = 0;
8864 struct nk_command_polygon_filled *cmd;
8865
8866 NK_ASSERT(b);
8867 if (!b || col.a == 0) return;
8868 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
8869 cmd = (struct nk_command_polygon_filled*)
8870 nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
8871 if (!cmd) return;
8872 cmd->color = col;
8873 cmd->point_count = (unsigned short)point_count;
8874 for (i = 0; i < point_count; ++i) {
8875 cmd->points[i].x = (short)points[i*2+0];
8876 cmd->points[i].y = (short)points[i*2+1];
8877 }
8878}
8879NK_API void
8881 float line_thickness, struct nk_color col)
8882{
8883 int i;
8884 nk_size size = 0;
8885 struct nk_command_polyline *cmd;
8886
8887 NK_ASSERT(b);
8888 if (!b || col.a == 0 || line_thickness <= 0) return;
8889 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
8890 cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
8891 if (!cmd) return;
8892 cmd->color = col;
8893 cmd->point_count = (unsigned short)point_count;
8894 cmd->line_thickness = (unsigned short)line_thickness;
8895 for (i = 0; i < point_count; ++i) {
8896 cmd->points[i].x = (short)points[i*2];
8897 cmd->points[i].y = (short)points[i*2+1];
8898 }
8899}
8900NK_API void
8901nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
8902 const struct nk_image *img, struct nk_color col)
8903{
8904 struct nk_command_image *cmd;
8905 NK_ASSERT(b);
8906 if (!b) return;
8907 if (b->use_clipping) {
8908 const struct nk_rect *c = &b->clip;
8909 if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
8910 return;
8911 }
8912
8913 cmd = (struct nk_command_image*)
8914 nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
8915 if (!cmd) return;
8916 cmd->x = (short)r.x;
8917 cmd->y = (short)r.y;
8918 cmd->w = (unsigned short)NK_MAX(0, r.w);
8919 cmd->h = (unsigned short)NK_MAX(0, r.h);
8920 cmd->img = *img;
8921 cmd->col = col;
8922}
8923NK_API void
8924nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
8926{
8927 struct nk_command_custom *cmd;
8928 NK_ASSERT(b);
8929 if (!b) return;
8930 if (b->use_clipping) {
8931 const struct nk_rect *c = &b->clip;
8932 if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
8933 return;
8934 }
8935
8936 cmd = (struct nk_command_custom*)
8937 nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
8938 if (!cmd) return;
8939 cmd->x = (short)r.x;
8940 cmd->y = (short)r.y;
8941 cmd->w = (unsigned short)NK_MAX(0, r.w);
8942 cmd->h = (unsigned short)NK_MAX(0, r.h);
8943 cmd->callback_data = usr;
8944 cmd->callback = cb;
8945}
8946NK_API void
8947nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
8948 const char *string, int length, const struct nk_user_font *font,
8949 struct nk_color bg, struct nk_color fg)
8950{
8951 float text_width = 0;
8952 struct nk_command_text *cmd;
8953
8954 NK_ASSERT(b);
8955 NK_ASSERT(font);
8956 if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
8957 if (b->use_clipping) {
8958 const struct nk_rect *c = &b->clip;
8959 if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
8960 return;
8961 }
8962
8963 /* make sure text fits inside bounds */
8964 text_width = font->width(font->userdata, font->height, string, length);
8965 if (text_width > r.w){
8966 int glyphs = 0;
8967 float txt_width = (float)text_width;
8968 length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
8969 }
8970
8971 if (!length) return;
8972 cmd = (struct nk_command_text*)
8973 nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
8974 if (!cmd) return;
8975 cmd->x = (short)r.x;
8976 cmd->y = (short)r.y;
8977 cmd->w = (unsigned short)r.w;
8978 cmd->h = (unsigned short)r.h;
8979 cmd->background = bg;
8980 cmd->foreground = fg;
8981 cmd->font = font;
8982 cmd->length = length;
8983 cmd->height = font->height;
8984 NK_MEMCPY(cmd->string, string, (nk_size)length);
8985 cmd->string[length] = '\0';
8986}
8987
8988
8989
8990
8991/* ===============================================================
8992 *
8993 * VERTEX
8994 *
8995 * ===============================================================*/
8996#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
8997NK_API void
8998nk_draw_list_init(struct nk_draw_list *list)
8999{
9000 nk_size i = 0;
9001 NK_ASSERT(list);
9002 if (!list) return;
9003 nk_zero(list, sizeof(*list));
9004 for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
9005 const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
9006 list->circle_vtx[i].x = (float)NK_COS(a);
9007 list->circle_vtx[i].y = (float)NK_SIN(a);
9008 }
9009}
9010NK_API void
9011nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
9012 struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
9013 enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
9014{
9015 NK_ASSERT(canvas);
9016 NK_ASSERT(config);
9017 NK_ASSERT(cmds);
9018 NK_ASSERT(vertices);
9019 NK_ASSERT(elements);
9020 if (!canvas || !config || !cmds || !vertices || !elements)
9021 return;
9022
9023 canvas->buffer = cmds;
9024 canvas->config = *config;
9025 canvas->elements = elements;
9026 canvas->vertices = vertices;
9027 canvas->line_AA = line_aa;
9028 canvas->shape_AA = shape_aa;
9029 canvas->clip_rect = nk_null_rect;
9030
9031 canvas->cmd_offset = 0;
9032 canvas->element_count = 0;
9033 canvas->vertex_count = 0;
9034 canvas->cmd_offset = 0;
9035 canvas->cmd_count = 0;
9036 canvas->path_count = 0;
9037}
9038NK_API const struct nk_draw_command*
9039nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
9040{
9041 nk_byte *memory;
9042 nk_size offset;
9043 const struct nk_draw_command *cmd;
9044
9045 NK_ASSERT(buffer);
9046 if (!buffer || !buffer->size || !canvas->cmd_count)
9047 return 0;
9048
9049 memory = (nk_byte*)buffer->memory.ptr;
9050 offset = buffer->memory.size - canvas->cmd_offset;
9051 cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
9052 return cmd;
9053}
9054NK_API const struct nk_draw_command*
9055nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
9056{
9057 nk_size size;
9058 nk_size offset;
9059 nk_byte *memory;
9060 const struct nk_draw_command *end;
9061
9062 NK_ASSERT(buffer);
9063 NK_ASSERT(canvas);
9064 if (!buffer || !canvas)
9065 return 0;
9066
9067 memory = (nk_byte*)buffer->memory.ptr;
9068 size = buffer->memory.size;
9069 offset = size - canvas->cmd_offset;
9070 end = nk_ptr_add(const struct nk_draw_command, memory, offset);
9071 end -= (canvas->cmd_count-1);
9072 return end;
9073}
9074NK_API const struct nk_draw_command*
9075nk__draw_list_next(const struct nk_draw_command *cmd,
9076 const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
9077{
9078 const struct nk_draw_command *end;
9079 NK_ASSERT(buffer);
9080 NK_ASSERT(canvas);
9081 if (!cmd || !buffer || !canvas)
9082 return 0;
9083
9084 end = nk__draw_list_end(canvas, buffer);
9085 if (cmd <= end) return 0;
9086 return (cmd-1);
9087}
9088NK_INTERN struct nk_vec2*
9089nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
9090{
9091 struct nk_vec2 *points;
9092 NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
9093 NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
9094 points = (struct nk_vec2*)
9095 nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
9096 point_size * (nk_size)count, point_align);
9097
9098 if (!points) return 0;
9099 if (!list->path_offset) {
9100 void *memory = nk_buffer_memory(list->buffer);
9101 list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
9102 }
9103 list->path_count += (unsigned int)count;
9104 return points;
9105}
9106NK_INTERN struct nk_vec2
9107nk_draw_list_path_last(struct nk_draw_list *list)
9108{
9109 void *memory;
9110 struct nk_vec2 *point;
9111 NK_ASSERT(list->path_count);
9112 memory = nk_buffer_memory(list->buffer);
9113 point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
9114 point += (list->path_count-1);
9115 return *point;
9116}
9117NK_INTERN struct nk_draw_command*
9118nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
9119 nk_handle texture)
9120{
9121 NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
9122 NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
9123 struct nk_draw_command *cmd;
9124
9125 NK_ASSERT(list);
9126 cmd = (struct nk_draw_command*)
9127 nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
9128
9129 if (!cmd) return 0;
9130 if (!list->cmd_count) {
9131 nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
9132 nk_size total = nk_buffer_total(list->buffer);
9133 memory = nk_ptr_add(nk_byte, memory, total);
9134 list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
9135 }
9136
9137 cmd->elem_count = 0;
9138 cmd->clip_rect = clip;
9139 cmd->texture = texture;
9140#ifdef NK_INCLUDE_COMMAND_USERDATA
9141 cmd->userdata = list->userdata;
9142#endif
9143
9144 list->cmd_count++;
9145 list->clip_rect = clip;
9146 return cmd;
9147}
9148NK_INTERN struct nk_draw_command*
9149nk_draw_list_command_last(struct nk_draw_list *list)
9150{
9151 void *memory;
9152 nk_size size;
9153 struct nk_draw_command *cmd;
9154 NK_ASSERT(list->cmd_count);
9155
9156 memory = nk_buffer_memory(list->buffer);
9157 size = nk_buffer_total(list->buffer);
9158 cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
9159 return (cmd - (list->cmd_count-1));
9160}
9161NK_INTERN void
9162nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
9163{
9164 NK_ASSERT(list);
9165 if (!list) return;
9166 if (!list->cmd_count) {
9167 nk_draw_list_push_command(list, rect, list->config.null.texture);
9168 } else {
9169 struct nk_draw_command *prev = nk_draw_list_command_last(list);
9170 if (prev->elem_count == 0)
9171 prev->clip_rect = rect;
9172 nk_draw_list_push_command(list, rect, prev->texture);
9173 }
9174}
9175NK_INTERN void
9176nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
9177{
9178 NK_ASSERT(list);
9179 if (!list) return;
9180 if (!list->cmd_count) {
9181 nk_draw_list_push_command(list, nk_null_rect, texture);
9182 } else {
9183 struct nk_draw_command *prev = nk_draw_list_command_last(list);
9184 if (prev->elem_count == 0) {
9185 prev->texture = texture;
9186 #ifdef NK_INCLUDE_COMMAND_USERDATA
9187 prev->userdata = list->userdata;
9188 #endif
9189 } else if (prev->texture.id != texture.id
9190 #ifdef NK_INCLUDE_COMMAND_USERDATA
9191 || prev->userdata.id != list->userdata.id
9192 #endif
9193 ) nk_draw_list_push_command(list, prev->clip_rect, texture);
9194 }
9195}
9196#ifdef NK_INCLUDE_COMMAND_USERDATA
9197NK_API void
9198nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
9199{
9200 list->userdata = userdata;
9201}
9202#endif
9203NK_INTERN void*
9204nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
9205{
9206 void *vtx;
9207 NK_ASSERT(list);
9208 if (!list) return 0;
9209 vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
9210 list->config.vertex_size*count, list->config.vertex_alignment);
9211 if (!vtx) return 0;
9212 list->vertex_count += (unsigned int)count;
9213
9214 /* This assert triggers because your are drawing a lot of stuff and nuklear
9215 * defined `nk_draw_index` as `nk_ushort` to safe space be default.
9216 *
9217 * So you reached the maximum number of indicies or rather vertexes.
9218 * To solve this issue please change typdef `nk_draw_index` to `nk_uint`
9219 * and don't forget to specify the new element size in your drawing
9220 * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements`
9221 * instead of specifing `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`.
9222 * Sorry for the inconvenience. */
9223 if(sizeof(nk_draw_index)==2) NK_ASSERT((list->vertex_count < NK_USHORT_MAX &&
9224 "To many verticies for 16-bit vertex indicies. Please read comment above on how to solve this problem"));
9225 return vtx;
9226}
9227NK_INTERN nk_draw_index*
9228nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
9229{
9230 nk_draw_index *ids;
9231 struct nk_draw_command *cmd;
9232 NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
9233 NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
9234 NK_ASSERT(list);
9235 if (!list) return 0;
9236
9237 ids = (nk_draw_index*)
9238 nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
9239 if (!ids) return 0;
9240 cmd = nk_draw_list_command_last(list);
9241 list->element_count += (unsigned int)count;
9242 cmd->elem_count += (unsigned int)count;
9243 return ids;
9244}
9245NK_INTERN int
9246nk_draw_vertex_layout_element_is_end_of_layout(
9247 const struct nk_draw_vertex_layout_element *element)
9248{
9249 return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
9250 element->format == NK_FORMAT_COUNT);
9251}
9252NK_INTERN void
9253nk_draw_vertex_color(void *attr, const float *vals,
9254 enum nk_draw_vertex_layout_format format)
9255{
9256 /* if this triggers you tried to provide a value format for a color */
9257 float val[4];
9258 NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
9259 NK_ASSERT(format <= NK_FORMAT_COLOR_END);
9260 if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
9261
9262 val[0] = NK_SATURATE(vals[0]);
9263 val[1] = NK_SATURATE(vals[1]);
9264 val[2] = NK_SATURATE(vals[2]);
9265 val[3] = NK_SATURATE(vals[3]);
9266
9267 switch (format) {
9268 default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
9269 case NK_FORMAT_R8G8B8A8:
9270 case NK_FORMAT_R8G8B8: {
9271 struct nk_color col = nk_rgba_fv(val);
9272 NK_MEMCPY(attr, &col.r, sizeof(col));
9273 } break;
9274 case NK_FORMAT_B8G8R8A8: {
9275 struct nk_color col = nk_rgba_fv(val);
9276 struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
9277 NK_MEMCPY(attr, &bgra, sizeof(bgra));
9278 } break;
9279 case NK_FORMAT_R16G15B16: {
9280 nk_ushort col[3];
9281 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
9282 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
9283 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
9284 NK_MEMCPY(attr, col, sizeof(col));
9285 } break;
9286 case NK_FORMAT_R16G15B16A16: {
9287 nk_ushort col[4];
9288 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
9289 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
9290 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
9291 col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX);
9292 NK_MEMCPY(attr, col, sizeof(col));
9293 } break;
9294 case NK_FORMAT_R32G32B32: {
9295 nk_uint col[3];
9296 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
9297 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
9298 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
9299 NK_MEMCPY(attr, col, sizeof(col));
9300 } break;
9301 case NK_FORMAT_R32G32B32A32: {
9302 nk_uint col[4];
9303 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
9304 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
9305 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
9306 col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX);
9307 NK_MEMCPY(attr, col, sizeof(col));
9308 } break;
9309 case NK_FORMAT_R32G32B32A32_FLOAT:
9310 NK_MEMCPY(attr, val, sizeof(float)*4);
9311 break;
9312 case NK_FORMAT_R32G32B32A32_DOUBLE: {
9313 double col[4];
9314 col[0] = (double)val[0];
9315 col[1] = (double)val[1];
9316 col[2] = (double)val[2];
9317 col[3] = (double)val[3];
9318 NK_MEMCPY(attr, col, sizeof(col));
9319 } break;
9320 case NK_FORMAT_RGB32:
9321 case NK_FORMAT_RGBA32: {
9322 struct nk_color col = nk_rgba_fv(val);
9323 nk_uint color = nk_color_u32(col);
9324 NK_MEMCPY(attr, &color, sizeof(color));
9325 } break; }
9326}
9327NK_INTERN void
9328nk_draw_vertex_element(void *dst, const float *values, int value_count,
9329 enum nk_draw_vertex_layout_format format)
9330{
9331 int value_index;
9332 void *attribute = dst;
9333 /* if this triggers you tried to provide a color format for a value */
9334 NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
9335 if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
9336 for (value_index = 0; value_index < value_count; ++value_index) {
9337 switch (format) {
9338 default: NK_ASSERT(0 && "invalid vertex layout format"); break;
9339 case NK_FORMAT_SCHAR: {
9340 char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX);
9341 NK_MEMCPY(attribute, &value, sizeof(value));
9342 attribute = (void*)((char*)attribute + sizeof(char));
9343 } break;
9344 case NK_FORMAT_SSHORT: {
9345 nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX);
9346 NK_MEMCPY(attribute, &value, sizeof(value));
9347 attribute = (void*)((char*)attribute + sizeof(value));
9348 } break;
9349 case NK_FORMAT_SINT: {
9350 nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX);
9351 NK_MEMCPY(attribute, &value, sizeof(value));
9352 attribute = (void*)((char*)attribute + sizeof(nk_int));
9353 } break;
9354 case NK_FORMAT_UCHAR: {
9355 unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX);
9356 NK_MEMCPY(attribute, &value, sizeof(value));
9357 attribute = (void*)((char*)attribute + sizeof(unsigned char));
9358 } break;
9359 case NK_FORMAT_USHORT: {
9360 nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX);
9361 NK_MEMCPY(attribute, &value, sizeof(value));
9362 attribute = (void*)((char*)attribute + sizeof(value));
9363 } break;
9364 case NK_FORMAT_UINT: {
9365 nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX);
9366 NK_MEMCPY(attribute, &value, sizeof(value));
9367 attribute = (void*)((char*)attribute + sizeof(nk_uint));
9368 } break;
9369 case NK_FORMAT_FLOAT:
9370 NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
9371 attribute = (void*)((char*)attribute + sizeof(float));
9372 break;
9373 case NK_FORMAT_DOUBLE: {
9374 double value = (double)values[value_index];
9375 NK_MEMCPY(attribute, &value, sizeof(value));
9376 attribute = (void*)((char*)attribute + sizeof(double));
9377 } break;
9378 }
9379 }
9380}
9381NK_INTERN void*
9382nk_draw_vertex(void *dst, const struct nk_convert_config *config,
9383 struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
9384{
9385 void *result = (void*)((char*)dst + config->vertex_size);
9386 const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
9387 while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
9388 void *address = (void*)((char*)dst + elem_iter->offset);
9389 switch (elem_iter->attribute) {
9390 case NK_VERTEX_ATTRIBUTE_COUNT:
9391 default: NK_ASSERT(0 && "wrong element attribute"); break;
9392 case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
9393 case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
9394 case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
9395 }
9396 elem_iter++;
9397 }
9398 return result;
9399}
9400NK_API void
9401nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
9402 const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
9403 float thickness, enum nk_anti_aliasing aliasing)
9404{
9405 nk_size count;
9406 int thick_line;
9407 struct nk_colorf col;
9408 struct nk_colorf col_trans;
9409 NK_ASSERT(list);
9410 if (!list || points_count < 2) return;
9411
9412 color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9413 count = points_count;
9414 if (!closed) count = points_count-1;
9415 thick_line = thickness > 1.0f;
9416
9417#ifdef NK_INCLUDE_COMMAND_USERDATA
9418 nk_draw_list_push_userdata(list, list->userdata);
9419#endif
9420
9421 color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9422 nk_color_fv(&col.r, color);
9423 col_trans = col;
9424 col_trans.a = 0;
9425
9426 if (aliasing == NK_ANTI_ALIASING_ON) {
9427 /* ANTI-ALIASED STROKE */
9428 const float AA_SIZE = 1.0f;
9429 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
9430 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
9431
9432 /* allocate vertices and elements */
9433 nk_size i1 = 0;
9434 nk_size vertex_offset;
9435 nk_size index = list->vertex_count;
9436
9437 const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12);
9438 const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
9439
9440 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9441 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9442
9443 nk_size size;
9444 struct nk_vec2 *normals, *temp;
9445 if (!vtx || !ids) return;
9446
9447 /* temporary allocate normals + points */
9448 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
9449 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
9450 size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
9451 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
9452 if (!normals) return;
9453 temp = normals + points_count;
9454
9455 /* make sure vertex pointer is still correct */
9456 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
9457
9458 /* calculate normals */
9459 for (i1 = 0; i1 < count; ++i1) {
9460 const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
9461 struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
9462 float len;
9463
9464 /* vec2 inverted length */
9465 len = nk_vec2_len_sqr(diff);
9466 if (len != 0.0f)
9467 len = nk_inv_sqrt(len);
9468 else len = 1.0f;
9469
9470 diff = nk_vec2_muls(diff, len);
9471 normals[i1].x = diff.y;
9472 normals[i1].y = -diff.x;
9473 }
9474
9475 if (!closed)
9476 normals[points_count-1] = normals[points_count-2];
9477
9478 if (!thick_line) {
9479 nk_size idx1, i;
9480 if (!closed) {
9481 struct nk_vec2 d;
9482 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
9483 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
9484 d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
9485 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
9486 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
9487 }
9488
9489 /* fill elements */
9490 idx1 = index;
9491 for (i1 = 0; i1 < count; i1++) {
9492 struct nk_vec2 dm;
9493 float dmr2;
9494 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
9495 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
9496
9497 /* average normals */
9498 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
9499 dmr2 = dm.x * dm.x + dm.y* dm.y;
9500 if (dmr2 > 0.000001f) {
9501 float scale = 1.0f/dmr2;
9502 scale = NK_MIN(100.0f, scale);
9503 dm = nk_vec2_muls(dm, scale);
9504 }
9505
9506 dm = nk_vec2_muls(dm, AA_SIZE);
9507 temp[i2*2+0] = nk_vec2_add(points[i2], dm);
9508 temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
9509
9510 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
9511 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
9512 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
9513 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
9514 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
9515 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
9516 ids += 12;
9517 idx1 = idx2;
9518 }
9519
9520 /* fill vertices */
9521 for (i = 0; i < points_count; ++i) {
9522 const struct nk_vec2 uv = list->config.null.uv;
9523 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
9524 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
9525 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
9526 }
9527 } else {
9528 nk_size idx1, i;
9529 const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
9530 if (!closed) {
9531 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
9532 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
9533
9534 temp[0] = nk_vec2_add(points[0], d1);
9535 temp[1] = nk_vec2_add(points[0], d2);
9536 temp[2] = nk_vec2_sub(points[0], d2);
9537 temp[3] = nk_vec2_sub(points[0], d1);
9538
9539 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
9540 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
9541
9542 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
9543 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
9544 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
9545 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
9546 }
9547
9548 /* add all elements */
9549 idx1 = index;
9550 for (i1 = 0; i1 < count; ++i1) {
9551 struct nk_vec2 dm_out, dm_in;
9552 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
9553 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
9554
9555 /* average normals */
9556 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
9557 float dmr2 = dm.x * dm.x + dm.y* dm.y;
9558 if (dmr2 > 0.000001f) {
9559 float scale = 1.0f/dmr2;
9560 scale = NK_MIN(100.0f, scale);
9561 dm = nk_vec2_muls(dm, scale);
9562 }
9563
9564 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
9565 dm_in = nk_vec2_muls(dm, half_inner_thickness);
9566 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
9567 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
9568 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
9569 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
9570
9571 /* add indexes */
9572 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
9573 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
9574 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
9575 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
9576 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
9577 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
9578 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
9579 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
9580 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
9581 ids += 18;
9582 idx1 = idx2;
9583 }
9584
9585 /* add vertices */
9586 for (i = 0; i < points_count; ++i) {
9587 const struct nk_vec2 uv = list->config.null.uv;
9588 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
9589 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
9590 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
9591 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
9592 }
9593 }
9594 /* free temporary normals + points */
9595 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
9596 } else {
9597 /* NON ANTI-ALIASED STROKE */
9598 nk_size i1 = 0;
9599 nk_size idx = list->vertex_count;
9600 const nk_size idx_count = count * 6;
9601 const nk_size vtx_count = count * 4;
9602 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9603 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9604 if (!vtx || !ids) return;
9605
9606 for (i1 = 0; i1 < count; ++i1) {
9607 float dx, dy;
9608 const struct nk_vec2 uv = list->config.null.uv;
9609 const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
9610 const struct nk_vec2 p1 = points[i1];
9611 const struct nk_vec2 p2 = points[i2];
9612 struct nk_vec2 diff = nk_vec2_sub(p2, p1);
9613 float len;
9614
9615 /* vec2 inverted length */
9616 len = nk_vec2_len_sqr(diff);
9617 if (len != 0.0f)
9618 len = nk_inv_sqrt(len);
9619 else len = 1.0f;
9620 diff = nk_vec2_muls(diff, len);
9621
9622 /* add vertices */
9623 dx = diff.x * (thickness * 0.5f);
9624 dy = diff.y * (thickness * 0.5f);
9625
9626 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
9627 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
9628 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
9629 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
9630
9631 ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
9632 ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
9633 ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
9634
9635 ids += 6;
9636 idx += 4;
9637 }
9638 }
9639}
9640NK_API void
9641nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
9642 const struct nk_vec2 *points, const unsigned int points_count,
9643 struct nk_color color, enum nk_anti_aliasing aliasing)
9644{
9645 struct nk_colorf col;
9646 struct nk_colorf col_trans;
9647
9648 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
9649 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
9650 NK_ASSERT(list);
9651 if (!list || points_count < 3) return;
9652
9653#ifdef NK_INCLUDE_COMMAND_USERDATA
9654 nk_draw_list_push_userdata(list, list->userdata);
9655#endif
9656
9657 color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9658 nk_color_fv(&col.r, color);
9659 col_trans = col;
9660 col_trans.a = 0;
9661
9662 if (aliasing == NK_ANTI_ALIASING_ON) {
9663 nk_size i = 0;
9664 nk_size i0 = 0;
9665 nk_size i1 = 0;
9666
9667 const float AA_SIZE = 1.0f;
9668 nk_size vertex_offset = 0;
9669 nk_size index = list->vertex_count;
9670
9671 const nk_size idx_count = (points_count-2)*3 + points_count*6;
9672 const nk_size vtx_count = (points_count*2);
9673
9674 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9675 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9676
9677 nk_size size = 0;
9678 struct nk_vec2 *normals = 0;
9679 unsigned int vtx_inner_idx = (unsigned int)(index + 0);
9680 unsigned int vtx_outer_idx = (unsigned int)(index + 1);
9681 if (!vtx || !ids) return;
9682
9683 /* temporary allocate normals */
9684 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
9685 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
9686 size = pnt_size * points_count;
9687 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
9688 if (!normals) return;
9689 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
9690
9691 /* add elements */
9692 for (i = 2; i < points_count; i++) {
9693 ids[0] = (nk_draw_index)(vtx_inner_idx);
9694 ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
9695 ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
9696 ids += 3;
9697 }
9698
9699 /* compute normals */
9700 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
9701 struct nk_vec2 p0 = points[i0];
9702 struct nk_vec2 p1 = points[i1];
9703 struct nk_vec2 diff = nk_vec2_sub(p1, p0);
9704
9705 /* vec2 inverted length */
9706 float len = nk_vec2_len_sqr(diff);
9707 if (len != 0.0f)
9708 len = nk_inv_sqrt(len);
9709 else len = 1.0f;
9710 diff = nk_vec2_muls(diff, len);
9711
9712 normals[i0].x = diff.y;
9713 normals[i0].y = -diff.x;
9714 }
9715
9716 /* add vertices + indexes */
9717 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
9718 const struct nk_vec2 uv = list->config.null.uv;
9719 struct nk_vec2 n0 = normals[i0];
9720 struct nk_vec2 n1 = normals[i1];
9721 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
9722 float dmr2 = dm.x*dm.x + dm.y*dm.y;
9723 if (dmr2 > 0.000001f) {
9724 float scale = 1.0f / dmr2;
9725 scale = NK_MIN(scale, 100.0f);
9726 dm = nk_vec2_muls(dm, scale);
9727 }
9728 dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
9729
9730 /* add vertices */
9731 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
9732 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
9733
9734 /* add indexes */
9735 ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
9736 ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
9737 ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
9738 ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
9739 ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
9740 ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
9741 ids += 6;
9742 }
9743 /* free temporary normals + points */
9744 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
9745 } else {
9746 nk_size i = 0;
9747 nk_size index = list->vertex_count;
9748 const nk_size idx_count = (points_count-2)*3;
9749 const nk_size vtx_count = points_count;
9750 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9751 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9752
9753 if (!vtx || !ids) return;
9754 for (i = 0; i < vtx_count; ++i)
9755 vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
9756 for (i = 2; i < points_count; ++i) {
9757 ids[0] = (nk_draw_index)index;
9758 ids[1] = (nk_draw_index)(index+ i - 1);
9759 ids[2] = (nk_draw_index)(index+i);
9760 ids += 3;
9761 }
9762 }
9763}
9764NK_API void
9765nk_draw_list_path_clear(struct nk_draw_list *list)
9766{
9767 NK_ASSERT(list);
9768 if (!list) return;
9769 nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
9770 list->path_count = 0;
9771 list->path_offset = 0;
9772}
9773NK_API void
9774nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
9775{
9776 struct nk_vec2 *points = 0;
9777 struct nk_draw_command *cmd = 0;
9778 NK_ASSERT(list);
9779 if (!list) return;
9780 if (!list->cmd_count)
9781 nk_draw_list_add_clip(list, nk_null_rect);
9782
9783 cmd = nk_draw_list_command_last(list);
9784 if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
9785 nk_draw_list_push_image(list, list->config.null.texture);
9786
9787 points = nk_draw_list_alloc_path(list, 1);
9788 if (!points) return;
9789 points[0] = pos;
9790}
9791NK_API void
9792nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
9793 float radius, int a_min, int a_max)
9794{
9795 int a = 0;
9796 NK_ASSERT(list);
9797 if (!list) return;
9798 if (a_min <= a_max) {
9799 for (a = a_min; a <= a_max; a++) {
9800 const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
9801 const float x = center.x + c.x * radius;
9802 const float y = center.y + c.y * radius;
9803 nk_draw_list_path_line_to(list, nk_vec2(x, y));
9804 }
9805 }
9806}
9807NK_API void
9808nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
9809 float radius, float a_min, float a_max, unsigned int segments)
9810{
9811 unsigned int i = 0;
9812 NK_ASSERT(list);
9813 if (!list) return;
9814 if (radius == 0.0f) return;
9815
9816 /* This algorithm for arc drawing relies on these two trigonometric identities[1]:
9817 sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
9818 cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
9819
9820 Two coordinates (x, y) of a point on a circle centered on
9821 the origin can be written in polar form as:
9822 x = r * cos(a)
9823 y = r * sin(a)
9824 where r is the radius of the circle,
9825 a is the angle between (x, y) and the origin.
9826
9827 This allows us to rotate the coordinates around the
9828 origin by an angle b using the following transformation:
9829 x' = r * cos(a + b) = x * cos(b) - y * sin(b)
9830 y' = r * sin(a + b) = y * cos(b) + x * sin(b)
9831
9832 [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
9833 */
9834 {const float d_angle = (a_max - a_min) / (float)segments;
9835 const float sin_d = (float)NK_SIN(d_angle);
9836 const float cos_d = (float)NK_COS(d_angle);
9837
9838 float cx = (float)NK_COS(a_min) * radius;
9839 float cy = (float)NK_SIN(a_min) * radius;
9840 for(i = 0; i <= segments; ++i) {
9841 float new_cx, new_cy;
9842 const float x = center.x + cx;
9843 const float y = center.y + cy;
9844 nk_draw_list_path_line_to(list, nk_vec2(x, y));
9845
9846 new_cx = cx * cos_d - cy * sin_d;
9847 new_cy = cy * cos_d + cx * sin_d;
9848 cx = new_cx;
9849 cy = new_cy;
9850 }}
9851}
9852NK_API void
9853nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
9854 struct nk_vec2 b, float rounding)
9855{
9856 float r;
9857 NK_ASSERT(list);
9858 if (!list) return;
9859 r = rounding;
9860 r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
9861 r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
9862
9863 if (r == 0.0f) {
9864 nk_draw_list_path_line_to(list, a);
9865 nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
9866 nk_draw_list_path_line_to(list, b);
9867 nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
9868 } else {
9869 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
9870 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
9871 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
9872 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
9873 }
9874}
9875NK_API void
9876nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
9877 struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
9878{
9879 float t_step;
9880 unsigned int i_step;
9881 struct nk_vec2 p1;
9882
9883 NK_ASSERT(list);
9884 NK_ASSERT(list->path_count);
9885 if (!list || !list->path_count) return;
9886 num_segments = NK_MAX(num_segments, 1);
9887
9888 p1 = nk_draw_list_path_last(list);
9889 t_step = 1.0f/(float)num_segments;
9890 for (i_step = 1; i_step <= num_segments; ++i_step) {
9891 float t = t_step * (float)i_step;
9892 float u = 1.0f - t;
9893 float w1 = u*u*u;
9894 float w2 = 3*u*u*t;
9895 float w3 = 3*u*t*t;
9896 float w4 = t * t *t;
9897 float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
9898 float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
9899 nk_draw_list_path_line_to(list, nk_vec2(x,y));
9900 }
9901}
9902NK_API void
9903nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
9904{
9905 struct nk_vec2 *points;
9906 NK_ASSERT(list);
9907 if (!list) return;
9908 points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
9909 nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
9910 nk_draw_list_path_clear(list);
9911}
9912NK_API void
9913nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
9914 enum nk_draw_list_stroke closed, float thickness)
9915{
9916 struct nk_vec2 *points;
9917 NK_ASSERT(list);
9918 if (!list) return;
9919 points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
9920 nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
9921 closed, thickness, list->config.line_AA);
9922 nk_draw_list_path_clear(list);
9923}
9924NK_API void
9925nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
9926 struct nk_vec2 b, struct nk_color col, float thickness)
9927{
9928 NK_ASSERT(list);
9929 if (!list || !col.a) return;
9930 if (list->line_AA == NK_ANTI_ALIASING_ON) {
9931 nk_draw_list_path_line_to(list, a);
9932 nk_draw_list_path_line_to(list, b);
9933 } else {
9934 nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
9935 nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
9936 }
9937 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
9938}
9939NK_API void
9940nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
9941 struct nk_color col, float rounding)
9942{
9943 NK_ASSERT(list);
9944 if (!list || !col.a) return;
9945
9946 if (list->line_AA == NK_ANTI_ALIASING_ON) {
9947 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
9948 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
9949 } else {
9950 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
9951 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
9952 } nk_draw_list_path_fill(list, col);
9953}
9954NK_API void
9955nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
9956 struct nk_color col, float rounding, float thickness)
9957{
9958 NK_ASSERT(list);
9959 if (!list || !col.a) return;
9960 if (list->line_AA == NK_ANTI_ALIASING_ON) {
9961 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
9962 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
9963 } else {
9964 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
9965 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
9966 } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
9967}
9968NK_API void
9969nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
9970 struct nk_color left, struct nk_color top, struct nk_color right,
9971 struct nk_color bottom)
9972{
9973 void *vtx;
9974 struct nk_colorf col_left, col_top;
9975 struct nk_colorf col_right, col_bottom;
9976 nk_draw_index *idx;
9977 nk_draw_index index;
9978
9979 nk_color_fv(&col_left.r, left);
9980 nk_color_fv(&col_right.r, right);
9981 nk_color_fv(&col_top.r, top);
9982 nk_color_fv(&col_bottom.r, bottom);
9983
9984 NK_ASSERT(list);
9985 if (!list) return;
9986
9987 nk_draw_list_push_image(list, list->config.null.texture);
9988 index = (nk_draw_index)list->vertex_count;
9989 vtx = nk_draw_list_alloc_vertices(list, 4);
9990 idx = nk_draw_list_alloc_elements(list, 6);
9991 if (!vtx || !idx) return;
9992
9993 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
9994 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
9995 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
9996
9997 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
9998 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
9999 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
10000 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
10001}
10002NK_API void
10003nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
10004 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
10005{
10006 NK_ASSERT(list);
10007 if (!list || !col.a) return;
10008 nk_draw_list_path_line_to(list, a);
10009 nk_draw_list_path_line_to(list, b);
10010 nk_draw_list_path_line_to(list, c);
10011 nk_draw_list_path_fill(list, col);
10012}
10013NK_API void
10014nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
10015 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
10016{
10017 NK_ASSERT(list);
10018 if (!list || !col.a) return;
10019 nk_draw_list_path_line_to(list, a);
10020 nk_draw_list_path_line_to(list, b);
10021 nk_draw_list_path_line_to(list, c);
10022 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
10023}
10024NK_API void
10025nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
10026 float radius, struct nk_color col, unsigned int segs)
10027{
10028 float a_max;
10029 NK_ASSERT(list);
10030 if (!list || !col.a) return;
10031 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
10032 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
10033 nk_draw_list_path_fill(list, col);
10034}
10035NK_API void
10036nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
10037 float radius, struct nk_color col, unsigned int segs, float thickness)
10038{
10039 float a_max;
10040 NK_ASSERT(list);
10041 if (!list || !col.a) return;
10042 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
10043 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
10044 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
10045}
10046NK_API void
10047nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
10048 struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
10049 struct nk_color col, unsigned int segments, float thickness)
10050{
10051 NK_ASSERT(list);
10052 if (!list || !col.a) return;
10053 nk_draw_list_path_line_to(list, p0);
10054 nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
10055 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
10056}
10057NK_INTERN void
10058nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
10059 struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
10060 struct nk_color color)
10061{
10062 void *vtx;
10063 struct nk_vec2 uvb;
10064 struct nk_vec2 uvd;
10065 struct nk_vec2 b;
10066 struct nk_vec2 d;
10067
10068 struct nk_colorf col;
10069 nk_draw_index *idx;
10070 nk_draw_index index;
10071 NK_ASSERT(list);
10072 if (!list) return;
10073
10074 nk_color_fv(&col.r, color);
10075 uvb = nk_vec2(uvc.x, uva.y);
10076 uvd = nk_vec2(uva.x, uvc.y);
10077 b = nk_vec2(c.x, a.y);
10078 d = nk_vec2(a.x, c.y);
10079
10080 index = (nk_draw_index)list->vertex_count;
10081 vtx = nk_draw_list_alloc_vertices(list, 4);
10082 idx = nk_draw_list_alloc_elements(list, 6);
10083 if (!vtx || !idx) return;
10084
10085 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
10086 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
10087 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
10088
10089 vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
10090 vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
10091 vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
10092 vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
10093}
10094NK_API void
10095nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
10096 struct nk_rect rect, struct nk_color color)
10097{
10098 NK_ASSERT(list);
10099 if (!list) return;
10100 /* push new command with given texture */
10101 nk_draw_list_push_image(list, texture.handle);
10102 if (nk_image_is_subimage(&texture)) {
10103 /* add region inside of the texture */
10104 struct nk_vec2 uv[2];
10105 uv[0].x = (float)texture.region[0]/(float)texture.w;
10106 uv[0].y = (float)texture.region[1]/(float)texture.h;
10107 uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
10108 uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
10109 nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
10110 nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color);
10111 } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
10112 nk_vec2(rect.x + rect.w, rect.y + rect.h),
10113 nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
10114}
10115NK_API void
10116nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
10117 struct nk_rect rect, const char *text, int len, float font_height,
10118 struct nk_color fg)
10119{
10120 float x = 0;
10121 int text_len = 0;
10122 nk_rune unicode = 0;
10123 nk_rune next = 0;
10124 int glyph_len = 0;
10125 int next_glyph_len = 0;
10126 struct nk_user_font_glyph g;
10127
10128 NK_ASSERT(list);
10129 if (!list || !len || !text) return;
10130 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
10131 list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
10132
10133 nk_draw_list_push_image(list, font->texture);
10134 x = rect.x;
10135 glyph_len = nk_utf_decode(text, &unicode, len);
10136 if (!glyph_len) return;
10137
10138 /* draw every glyph image */
10139 fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
10140 while (text_len < len && glyph_len) {
10141 float gx, gy, gh, gw;
10142 float char_width = 0;
10143 if (unicode == NK_UTF_INVALID) break;
10144
10145 /* query currently drawn glyph information */
10146 next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
10147 font->query(font->userdata, font_height, &g, unicode,
10148 (next == NK_UTF_INVALID) ? '\0' : next);
10149
10150 /* calculate and draw glyph drawing rectangle and image */
10151 gx = x + g.offset.x;
10152 gy = rect.y + g.offset.y;
10153 gw = g.width; gh = g.height;
10154 char_width = g.xadvance;
10155 nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
10156 g.uv[0], g.uv[1], fg);
10157
10158 /* offset next glyph */
10159 text_len += glyph_len;
10160 x += char_width;
10161 glyph_len = next_glyph_len;
10162 unicode = next;
10163 }
10164}
10166nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
10167 struct nk_buffer *vertices, struct nk_buffer *elements,
10168 const struct nk_convert_config *config)
10169{
10171 const struct nk_command *cmd;
10172 NK_ASSERT(ctx);
10173 NK_ASSERT(cmds);
10174 NK_ASSERT(vertices);
10175 NK_ASSERT(elements);
10176 NK_ASSERT(config);
10177 NK_ASSERT(config->vertex_layout);
10178 NK_ASSERT(config->vertex_size);
10179 if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
10181
10182 nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
10183 config->line_AA, config->shape_AA);
10184 nk_foreach(cmd, ctx)
10185 {
10186#ifdef NK_INCLUDE_COMMAND_USERDATA
10187 ctx->draw_list.userdata = cmd->userdata;
10188#endif
10189 switch (cmd->type) {
10190 case NK_COMMAND_NOP: break;
10191 case NK_COMMAND_SCISSOR: {
10192 const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
10193 nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
10194 } break;
10195 case NK_COMMAND_LINE: {
10196 const struct nk_command_line *l = (const struct nk_command_line*)cmd;
10197 nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
10198 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
10199 } break;
10200 case NK_COMMAND_CURVE: {
10201 const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
10202 nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
10203 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
10204 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
10206 } break;
10207 case NK_COMMAND_RECT: {
10208 const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
10209 nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10210 r->color, (float)r->rounding, r->line_thickness);
10211 } break;
10213 const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
10214 nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10215 r->color, (float)r->rounding);
10216 } break;
10218 const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
10219 nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10220 r->left, r->top, r->right, r->bottom);
10221 } break;
10222 case NK_COMMAND_CIRCLE: {
10223 const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
10224 nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
10225 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
10227 } break;
10229 const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
10230 nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
10231 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
10232 config->circle_segment_count);
10233 } break;
10234 case NK_COMMAND_ARC: {
10235 const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
10236 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
10237 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
10238 c->a[0], c->a[1], config->arc_segment_count);
10239 nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
10240 } break;
10241 case NK_COMMAND_ARC_FILLED: {
10242 const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
10243 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
10244 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
10245 c->a[0], c->a[1], config->arc_segment_count);
10246 nk_draw_list_path_fill(&ctx->draw_list, c->color);
10247 } break;
10248 case NK_COMMAND_TRIANGLE: {
10249 const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
10250 nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
10251 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
10252 t->line_thickness);
10253 } break;
10255 const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
10256 nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
10257 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
10258 } break;
10259 case NK_COMMAND_POLYGON: {
10260 int i;
10261 const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
10262 for (i = 0; i < p->point_count; ++i) {
10263 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10264 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10265 }
10266 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
10267 } break;
10269 int i;
10270 const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
10271 for (i = 0; i < p->point_count; ++i) {
10272 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10273 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10274 }
10275 nk_draw_list_path_fill(&ctx->draw_list, p->color);
10276 } break;
10277 case NK_COMMAND_POLYLINE: {
10278 int i;
10279 const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
10280 for (i = 0; i < p->point_count; ++i) {
10281 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10282 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10283 }
10284 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
10285 } break;
10286 case NK_COMMAND_TEXT: {
10287 const struct nk_command_text *t = (const struct nk_command_text*)cmd;
10288 nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
10289 t->string, t->length, t->height, t->foreground);
10290 } break;
10291 case NK_COMMAND_IMAGE: {
10292 const struct nk_command_image *i = (const struct nk_command_image*)cmd;
10293 nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
10294 } break;
10295 case NK_COMMAND_CUSTOM: {
10296 const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
10297 c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
10298 } break;
10299 default: break;
10300 }
10301 }
10302 res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
10303 res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
10304 res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
10305 return res;
10306}
10307NK_API const struct nk_draw_command*
10308nk__draw_begin(const struct nk_context *ctx,
10309 const struct nk_buffer *buffer)
10310{
10311 return nk__draw_list_begin(&ctx->draw_list, buffer);
10312}
10313NK_API const struct nk_draw_command*
10314nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
10315{
10316 return nk__draw_list_end(&ctx->draw_list, buffer);
10317}
10318NK_API const struct nk_draw_command*
10319nk__draw_next(const struct nk_draw_command *cmd,
10320 const struct nk_buffer *buffer, const struct nk_context *ctx)
10321{
10322 return nk__draw_list_next(cmd, buffer, &ctx->draw_list);
10323}
10324#endif
10325
10326
10327
10328
10329#ifdef NK_INCLUDE_FONT_BAKING
10330/* -------------------------------------------------------------
10331 *
10332 * RECT PACK
10333 *
10334 * --------------------------------------------------------------*/
10335/* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
10336/* Sean Barrett 2014 */
10337#define NK_RP__MAXVAL 0xffff
10338typedef unsigned short nk_rp_coord;
10339
10340struct nk_rp_rect {
10341 /* reserved for your use: */
10342 int id;
10343 /* input: */
10344 nk_rp_coord w, h;
10345 /* output: */
10346 nk_rp_coord x, y;
10347 int was_packed;
10348 /* non-zero if valid packing */
10349}; /* 16 bytes, nominally */
10350
10351struct nk_rp_node {
10352 nk_rp_coord x,y;
10353 struct nk_rp_node *next;
10354};
10355
10356struct nk_rp_context {
10357 int width;
10358 int height;
10359 int align;
10360 int init_mode;
10361 int heuristic;
10362 int num_nodes;
10363 struct nk_rp_node *active_head;
10364 struct nk_rp_node *free_head;
10365 struct nk_rp_node extra[2];
10366 /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
10367};
10368
10369struct nk_rp__findresult {
10370 int x,y;
10371 struct nk_rp_node **prev_link;
10372};
10373
10374enum NK_RP_HEURISTIC {
10375 NK_RP_HEURISTIC_Skyline_default=0,
10376 NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
10377 NK_RP_HEURISTIC_Skyline_BF_sortHeight
10378};
10379enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
10380
10381NK_INTERN void
10382nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
10383{
10384 if (allow_out_of_mem)
10385 /* if it's ok to run out of memory, then don't bother aligning them; */
10386 /* this gives better packing, but may fail due to OOM (even though */
10387 /* the rectangles easily fit). @TODO a smarter approach would be to only */
10388 /* quantize once we've hit OOM, then we could get rid of this parameter. */
10389 context->align = 1;
10390 else {
10391 /* if it's not ok to run out of memory, then quantize the widths */
10392 /* so that num_nodes is always enough nodes. */
10393 /* */
10394 /* I.e. num_nodes * align >= width */
10395 /* align >= width / num_nodes */
10396 /* align = ceil(width/num_nodes) */
10397 context->align = (context->width + context->num_nodes-1) / context->num_nodes;
10398 }
10399}
10400NK_INTERN void
10401nk_rp_init_target(struct nk_rp_context *context, int width, int height,
10402 struct nk_rp_node *nodes, int num_nodes)
10403{
10404 int i;
10405#ifndef STBRP_LARGE_RECTS
10406 NK_ASSERT(width <= 0xffff && height <= 0xffff);
10407#endif
10408
10409 for (i=0; i < num_nodes-1; ++i)
10410 nodes[i].next = &nodes[i+1];
10411 nodes[i].next = 0;
10412 context->init_mode = NK_RP__INIT_skyline;
10413 context->heuristic = NK_RP_HEURISTIC_Skyline_default;
10414 context->free_head = &nodes[0];
10415 context->active_head = &context->extra[0];
10416 context->width = width;
10417 context->height = height;
10418 context->num_nodes = num_nodes;
10419 nk_rp_setup_allow_out_of_mem(context, 0);
10420
10421 /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
10422 context->extra[0].x = 0;
10423 context->extra[0].y = 0;
10424 context->extra[0].next = &context->extra[1];
10425 context->extra[1].x = (nk_rp_coord) width;
10426 context->extra[1].y = 65535;
10427 context->extra[1].next = 0;
10428}
10429/* find minimum y position if it starts at x1 */
10430NK_INTERN int
10431nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
10432 int x0, int width, int *pwaste)
10433{
10434 struct nk_rp_node *node = first;
10435 int x1 = x0 + width;
10436 int min_y, visited_width, waste_area;
10437 NK_ASSERT(first->x <= x0);
10438 NK_UNUSED(c);
10439
10440 NK_ASSERT(node->next->x > x0);
10441 /* we ended up handling this in the caller for efficiency */
10442 NK_ASSERT(node->x <= x0);
10443
10444 min_y = 0;
10445 waste_area = 0;
10446 visited_width = 0;
10447 while (node->x < x1)
10448 {
10449 if (node->y > min_y) {
10450 /* raise min_y higher. */
10451 /* we've accounted for all waste up to min_y, */
10452 /* but we'll now add more waste for everything we've visited */
10453 waste_area += visited_width * (node->y - min_y);
10454 min_y = node->y;
10455 /* the first time through, visited_width might be reduced */
10456 if (node->x < x0)
10457 visited_width += node->next->x - x0;
10458 else
10459 visited_width += node->next->x - node->x;
10460 } else {
10461 /* add waste area */
10462 int under_width = node->next->x - node->x;
10463 if (under_width + visited_width > width)
10464 under_width = width - visited_width;
10465 waste_area += under_width * (min_y - node->y);
10466 visited_width += under_width;
10467 }
10468 node = node->next;
10469 }
10470 *pwaste = waste_area;
10471 return min_y;
10472}
10473NK_INTERN struct nk_rp__findresult
10474nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
10475{
10476 int best_waste = (1<<30), best_x, best_y = (1 << 30);
10477 struct nk_rp__findresult fr;
10478 struct nk_rp_node **prev, *node, *tail, **best = 0;
10479
10480 /* align to multiple of c->align */
10481 width = (width + c->align - 1);
10482 width -= width % c->align;
10483 NK_ASSERT(width % c->align == 0);
10484
10485 node = c->active_head;
10486 prev = &c->active_head;
10487 while (node->x + width <= c->width) {
10488 int y,waste;
10489 y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
10490 /* actually just want to test BL */
10491 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
10492 /* bottom left */
10493 if (y < best_y) {
10494 best_y = y;
10495 best = prev;
10496 }
10497 } else {
10498 /* best-fit */
10499 if (y + height <= c->height) {
10500 /* can only use it if it first vertically */
10501 if (y < best_y || (y == best_y && waste < best_waste)) {
10502 best_y = y;
10503 best_waste = waste;
10504 best = prev;
10505 }
10506 }
10507 }
10508 prev = &node->next;
10509 node = node->next;
10510 }
10511 best_x = (best == 0) ? 0 : (*best)->x;
10512
10513 /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
10514 /* */
10515 /* e.g, if fitting */
10516 /* */
10517 /* ____________________ */
10518 /* |____________________| */
10519 /* */
10520 /* into */
10521 /* */
10522 /* | | */
10523 /* | ____________| */
10524 /* |____________| */
10525 /* */
10526 /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
10527 /* */
10528 /* This makes BF take about 2x the time */
10529 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
10530 {
10531 tail = c->active_head;
10532 node = c->active_head;
10533 prev = &c->active_head;
10534 /* find first node that's admissible */
10535 while (tail->x < width)
10536 tail = tail->next;
10537 while (tail)
10538 {
10539 int xpos = tail->x - width;
10540 int y,waste;
10541 NK_ASSERT(xpos >= 0);
10542 /* find the left position that matches this */
10543 while (node->next->x <= xpos) {
10544 prev = &node->next;
10545 node = node->next;
10546 }
10547 NK_ASSERT(node->next->x > xpos && node->x <= xpos);
10548 y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
10549 if (y + height < c->height) {
10550 if (y <= best_y) {
10551 if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
10552 best_x = xpos;
10553 NK_ASSERT(y <= best_y);
10554 best_y = y;
10555 best_waste = waste;
10556 best = prev;
10557 }
10558 }
10559 }
10560 tail = tail->next;
10561 }
10562 }
10563 fr.prev_link = best;
10564 fr.x = best_x;
10565 fr.y = best_y;
10566 return fr;
10567}
10568NK_INTERN struct nk_rp__findresult
10569nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
10570{
10571 /* find best position according to heuristic */
10572 struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
10573 struct nk_rp_node *node, *cur;
10574
10575 /* bail if: */
10576 /* 1. it failed */
10577 /* 2. the best node doesn't fit (we don't always check this) */
10578 /* 3. we're out of memory */
10579 if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
10580 res.prev_link = 0;
10581 return res;
10582 }
10583
10584 /* on success, create new node */
10585 node = context->free_head;
10586 node->x = (nk_rp_coord) res.x;
10587 node->y = (nk_rp_coord) (res.y + height);
10588
10589 context->free_head = node->next;
10590
10591 /* insert the new node into the right starting point, and */
10592 /* let 'cur' point to the remaining nodes needing to be */
10593 /* stitched back in */
10594 cur = *res.prev_link;
10595 if (cur->x < res.x) {
10596 /* preserve the existing one, so start testing with the next one */
10597 struct nk_rp_node *next = cur->next;
10598 cur->next = node;
10599 cur = next;
10600 } else {
10601 *res.prev_link = node;
10602 }
10603
10604 /* from here, traverse cur and free the nodes, until we get to one */
10605 /* that shouldn't be freed */
10606 while (cur->next && cur->next->x <= res.x + width) {
10607 struct nk_rp_node *next = cur->next;
10608 /* move the current node to the free list */
10609 cur->next = context->free_head;
10610 context->free_head = cur;
10611 cur = next;
10612 }
10613 /* stitch the list back in */
10614 node->next = cur;
10615
10616 if (cur->x < res.x + width)
10617 cur->x = (nk_rp_coord) (res.x + width);
10618 return res;
10619}
10620NK_INTERN int
10621nk_rect_height_compare(const void *a, const void *b)
10622{
10623 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
10624 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
10625 if (p->h > q->h)
10626 return -1;
10627 if (p->h < q->h)
10628 return 1;
10629 return (p->w > q->w) ? -1 : (p->w < q->w);
10630}
10631NK_INTERN int
10632nk_rect_original_order(const void *a, const void *b)
10633{
10634 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
10635 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
10636 return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
10637}
10638NK_INTERN void
10639nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
10640{
10641 /* iterative quick sort */
10642 #define NK_MAX_SORT_STACK 64
10643 unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
10644 unsigned seed = len/2 * 69069+1;
10645 for (;;) {
10646 for (; left+1 < len; len++) {
10647 struct nk_rp_rect pivot, tmp;
10648 if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
10649 pivot = array[left+seed%(len-left)];
10650 seed = seed * 69069 + 1;
10651 stack[pos++] = len;
10652 for (right = left-1;;) {
10653 while (cmp(&array[++right], &pivot) < 0);
10654 while (cmp(&pivot, &array[--len]) < 0);
10655 if (right >= len) break;
10656 tmp = array[right];
10657 array[right] = array[len];
10658 array[len] = tmp;
10659 }
10660 }
10661 if (pos == 0) break;
10662 left = len;
10663 len = stack[--pos];
10664 }
10665 #undef NK_MAX_SORT_STACK
10666}
10667NK_INTERN void
10668nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
10669{
10670 int i;
10671 /* we use the 'was_packed' field internally to allow sorting/unsorting */
10672 for (i=0; i < num_rects; ++i) {
10673 rects[i].was_packed = i;
10674 }
10675
10676 /* sort according to heuristic */
10677 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
10678
10679 for (i=0; i < num_rects; ++i) {
10680 struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
10681 if (fr.prev_link) {
10682 rects[i].x = (nk_rp_coord) fr.x;
10683 rects[i].y = (nk_rp_coord) fr.y;
10684 } else {
10685 rects[i].x = rects[i].y = NK_RP__MAXVAL;
10686 }
10687 }
10688
10689 /* unsort */
10690 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
10691
10692 /* set was_packed flags */
10693 for (i=0; i < num_rects; ++i)
10694 rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
10695}
10696
10697/*
10698 * ==============================================================
10699 *
10700 * TRUETYPE
10701 *
10702 * ===============================================================
10703 */
10704/* stb_truetype.h - v1.07 - public domain */
10705#define NK_TT_MAX_OVERSAMPLE 8
10706#define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1)
10707
10708struct nk_tt_bakedchar {
10709 unsigned short x0,y0,x1,y1;
10710 /* coordinates of bbox in bitmap */
10711 float xoff,yoff,xadvance;
10712};
10713
10714struct nk_tt_aligned_quad{
10715 float x0,y0,s0,t0; /* top-left */
10716 float x1,y1,s1,t1; /* bottom-right */
10717};
10718
10719struct nk_tt_packedchar {
10720 unsigned short x0,y0,x1,y1;
10721 /* coordinates of bbox in bitmap */
10722 float xoff,yoff,xadvance;
10723 float xoff2,yoff2;
10724};
10725
10726struct nk_tt_pack_range {
10727 float font_size;
10728 int first_unicode_codepoint_in_range;
10729 /* if non-zero, then the chars are continuous, and this is the first codepoint */
10730 int *array_of_unicode_codepoints;
10731 /* if non-zero, then this is an array of unicode codepoints */
10732 int num_chars;
10733 struct nk_tt_packedchar *chardata_for_range; /* output */
10734 unsigned char h_oversample, v_oversample;
10735 /* don't set these, they're used internally */
10736};
10737
10738struct nk_tt_pack_context {
10739 void *pack_info;
10740 int width;
10741 int height;
10742 int stride_in_bytes;
10743 int padding;
10744 unsigned int h_oversample, v_oversample;
10745 unsigned char *pixels;
10746 void *nodes;
10747};
10748
10749struct nk_tt_fontinfo {
10750 const unsigned char* data; /* pointer to .ttf file */
10751 int fontstart;/* offset of start of font */
10752 int numGlyphs;/* number of glyphs, needed for range checking */
10753 int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
10754 int index_map; /* a cmap mapping for our chosen character encoding */
10755 int indexToLocFormat; /* format needed to map from glyph index to glyph */
10756};
10757
10758enum {
10759 NK_TT_vmove=1,
10760 NK_TT_vline,
10761 NK_TT_vcurve
10762};
10763
10764struct nk_tt_vertex {
10765 short x,y,cx,cy;
10766 unsigned char type,padding;
10767};
10768
10769struct nk_tt__bitmap{
10770 int w,h,stride;
10771 unsigned char *pixels;
10772};
10773
10774struct nk_tt__hheap_chunk {
10775 struct nk_tt__hheap_chunk *next;
10776};
10777struct nk_tt__hheap {
10778 struct nk_allocator alloc;
10779 struct nk_tt__hheap_chunk *head;
10780 void *first_free;
10781 int num_remaining_in_head_chunk;
10782};
10783
10784struct nk_tt__edge {
10785 float x0,y0, x1,y1;
10786 int invert;
10787};
10788
10789struct nk_tt__active_edge {
10790 struct nk_tt__active_edge *next;
10791 float fx,fdx,fdy;
10792 float direction;
10793 float sy;
10794 float ey;
10795};
10796struct nk_tt__point {float x,y;};
10797
10798#define NK_TT_MACSTYLE_DONTCARE 0
10799#define NK_TT_MACSTYLE_BOLD 1
10800#define NK_TT_MACSTYLE_ITALIC 2
10801#define NK_TT_MACSTYLE_UNDERSCORE 4
10802#define NK_TT_MACSTYLE_NONE 8
10803/* <= not same as 0, this makes us check the bitfield is 0 */
10804
10805enum { /* platformID */
10806 NK_TT_PLATFORM_ID_UNICODE =0,
10807 NK_TT_PLATFORM_ID_MAC =1,
10808 NK_TT_PLATFORM_ID_ISO =2,
10809 NK_TT_PLATFORM_ID_MICROSOFT =3
10810};
10811
10812enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
10813 NK_TT_UNICODE_EID_UNICODE_1_0 =0,
10814 NK_TT_UNICODE_EID_UNICODE_1_1 =1,
10815 NK_TT_UNICODE_EID_ISO_10646 =2,
10816 NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
10817 NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
10818};
10819
10820enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
10821 NK_TT_MS_EID_SYMBOL =0,
10822 NK_TT_MS_EID_UNICODE_BMP =1,
10823 NK_TT_MS_EID_SHIFTJIS =2,
10824 NK_TT_MS_EID_UNICODE_FULL =10
10825};
10826
10827enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
10828 NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4,
10829 NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5,
10830 NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6,
10831 NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7
10832};
10833
10834enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
10835 /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
10836 NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410,
10837 NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411,
10838 NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412,
10839 NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419,
10840 NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409,
10841 NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D
10842};
10843
10844enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
10845 NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11,
10846 NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23,
10847 NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32,
10848 NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 ,
10849 NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 ,
10850 NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
10851 NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19
10852};
10853
10854#define nk_ttBYTE(p) (* (const nk_byte *) (p))
10855#define nk_ttCHAR(p) (* (const char *) (p))
10856
10857#if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
10858 #define nk_ttUSHORT(p) (* (nk_ushort *) (p))
10859 #define nk_ttSHORT(p) (* (nk_short *) (p))
10860 #define nk_ttULONG(p) (* (nk_uint *) (p))
10861 #define nk_ttLONG(p) (* (nk_int *) (p))
10862#else
10863 static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
10864 static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); }
10865 static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
10866#endif
10867
10868#define nk_tt_tag4(p,c0,c1,c2,c3)\
10869 ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
10870#define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
10871
10872NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
10873 int glyph_index, struct nk_tt_vertex **pvertices);
10874
10876nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
10877{
10878 /* @OPTIMIZE: binary search */
10879 nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
10880 nk_uint tabledir = fontstart + 12;
10881 nk_int i;
10882 for (i = 0; i < num_tables; ++i) {
10883 nk_uint loc = tabledir + (nk_uint)(16*i);
10884 if (nk_tt_tag(data+loc+0, tag))
10885 return nk_ttULONG(data+loc+8);
10886 }
10887 return 0;
10888}
10889NK_INTERN int
10890nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
10891{
10892 nk_uint cmap, t;
10893 nk_int i,numTables;
10894 const nk_byte *data = (const nk_byte *) data2;
10895
10896 info->data = data;
10897 info->fontstart = fontstart;
10898
10899 cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */
10900 info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
10901 info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
10902 info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
10903 info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
10904 info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
10905 info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
10906 if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
10907 return 0;
10908
10909 t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
10910 if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
10911 else info->numGlyphs = 0xffff;
10912
10913 /* find a cmap encoding table we understand *now* to avoid searching */
10914 /* later. (todo: could make this installable) */
10915 /* the same regardless of glyph. */
10916 numTables = nk_ttUSHORT(data + cmap + 2);
10917 info->index_map = 0;
10918 for (i=0; i < numTables; ++i)
10919 {
10920 nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
10921 /* find an encoding we understand: */
10922 switch(nk_ttUSHORT(data+encoding_record)) {
10923 case NK_TT_PLATFORM_ID_MICROSOFT:
10924 switch (nk_ttUSHORT(data+encoding_record+2)) {
10925 case NK_TT_MS_EID_UNICODE_BMP:
10926 case NK_TT_MS_EID_UNICODE_FULL:
10927 /* MS/Unicode */
10928 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
10929 break;
10930 default: break;
10931 } break;
10932 case NK_TT_PLATFORM_ID_UNICODE:
10933 /* Mac/iOS has these */
10934 /* all the encodingIDs are unicode, so we don't bother to check it */
10935 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
10936 break;
10937 default: break;
10938 }
10939 }
10940 if (info->index_map == 0)
10941 return 0;
10942 info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
10943 return 1;
10944}
10945NK_INTERN int
10946nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
10947{
10948 const nk_byte *data = info->data;
10949 nk_uint index_map = (nk_uint)info->index_map;
10950
10951 nk_ushort format = nk_ttUSHORT(data + index_map + 0);
10952 if (format == 0) { /* apple byte encoding */
10953 nk_int bytes = nk_ttUSHORT(data + index_map + 2);
10954 if (unicode_codepoint < bytes-6)
10955 return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
10956 return 0;
10957 } else if (format == 6) {
10958 nk_uint first = nk_ttUSHORT(data + index_map + 6);
10959 nk_uint count = nk_ttUSHORT(data + index_map + 8);
10960 if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
10961 return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
10962 return 0;
10963 } else if (format == 2) {
10964 NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
10965 return 0;
10966 } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
10967 nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
10968 nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
10969 nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
10970 nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
10971
10972 /* do a binary search of the segments */
10973 nk_uint endCount = index_map + 14;
10974 nk_uint search = endCount;
10975
10976 if (unicode_codepoint > 0xffff)
10977 return 0;
10978
10979 /* they lie from endCount .. endCount + segCount */
10980 /* but searchRange is the nearest power of two, so... */
10981 if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
10982 search += (nk_uint)(rangeShift*2);
10983
10984 /* now decrement to bias correctly to find smallest */
10985 search -= 2;
10986 while (entrySelector) {
10987 nk_ushort end;
10988 searchRange >>= 1;
10989 end = nk_ttUSHORT(data + search + searchRange*2);
10990 if (unicode_codepoint > end)
10991 search += (nk_uint)(searchRange*2);
10992 --entrySelector;
10993 }
10994 search += 2;
10995
10996 {
10997 nk_ushort offset, start;
10998 nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
10999
11000 NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
11001 start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
11002 if (unicode_codepoint < start)
11003 return 0;
11004
11005 offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
11006 if (offset == 0)
11007 return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
11008
11009 return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
11010 }
11011 } else if (format == 12 || format == 13) {
11012 nk_uint ngroups = nk_ttULONG(data+index_map+12);
11013 nk_int low,high;
11014 low = 0; high = (nk_int)ngroups;
11015 /* Binary search the right group. */
11016 while (low < high) {
11017 nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
11018 nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
11019 nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
11020 if ((nk_uint) unicode_codepoint < start_char)
11021 high = mid;
11022 else if ((nk_uint) unicode_codepoint > end_char)
11023 low = mid+1;
11024 else {
11025 nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
11026 if (format == 12)
11027 return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
11028 else /* format == 13 */
11029 return (int)start_glyph;
11030 }
11031 }
11032 return 0; /* not found */
11033 }
11034 /* @TODO */
11035 NK_ASSERT(0);
11036 return 0;
11037}
11038NK_INTERN void
11039nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
11040{
11041 v->type = type;
11042 v->x = (nk_short) x;
11043 v->y = (nk_short) y;
11044 v->cx = (nk_short) cx;
11045 v->cy = (nk_short) cy;
11046}
11047NK_INTERN int
11048nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
11049{
11050 int g1,g2;
11051 if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
11052 if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */
11053
11054 if (info->indexToLocFormat == 0) {
11055 g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
11056 g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
11057 } else {
11058 g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
11059 g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
11060 }
11061 return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
11062}
11063NK_INTERN int
11064nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
11065 int *x0, int *y0, int *x1, int *y1)
11066{
11067 int g = nk_tt__GetGlyfOffset(info, glyph_index);
11068 if (g < 0) return 0;
11069
11070 if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
11071 if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
11072 if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
11073 if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
11074 return 1;
11075}
11076NK_INTERN int
11077nk_tt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
11078 int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
11079{
11080 if (start_off) {
11081 if (was_off)
11082 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
11083 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
11084 } else {
11085 if (was_off)
11086 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
11087 else
11088 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
11089 }
11090 return num_vertices;
11091}
11092NK_INTERN int
11093nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
11094 int glyph_index, struct nk_tt_vertex **pvertices)
11095{
11096 nk_short numberOfContours;
11097 const nk_byte *endPtsOfContours;
11098 const nk_byte *data = info->data;
11099 struct nk_tt_vertex *vertices=0;
11100 int num_vertices=0;
11101 int g = nk_tt__GetGlyfOffset(info, glyph_index);
11102 *pvertices = 0;
11103
11104 if (g < 0) return 0;
11105 numberOfContours = nk_ttSHORT(data + g);
11106 if (numberOfContours > 0) {
11107 nk_byte flags=0,flagcount;
11108 nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
11109 nk_int x,y,cx,cy,sx,sy, scx,scy;
11110 const nk_byte *points;
11111 endPtsOfContours = (data + g + 10);
11112 ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
11113 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
11114
11115 n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
11116 m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */
11117 vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
11118 if (vertices == 0)
11119 return 0;
11120
11121 next_move = 0;
11122 flagcount=0;
11123
11124 /* in first pass, we load uninterpreted data into the allocated array */
11125 /* above, shifted to the end of the array so we won't overwrite it when */
11126 /* we create our final data starting from the front */
11127 off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
11128
11129 /* first load flags */
11130 for (i=0; i < n; ++i) {
11131 if (flagcount == 0) {
11132 flags = *points++;
11133 if (flags & 8)
11134 flagcount = *points++;
11135 } else --flagcount;
11136 vertices[off+i].type = flags;
11137 }
11138
11139 /* now load x coordinates */
11140 x=0;
11141 for (i=0; i < n; ++i) {
11142 flags = vertices[off+i].type;
11143 if (flags & 2) {
11144 nk_short dx = *points++;
11145 x += (flags & 16) ? dx : -dx; /* ??? */
11146 } else {
11147 if (!(flags & 16)) {
11148 x = x + (nk_short) (points[0]*256 + points[1]);
11149 points += 2;
11150 }
11151 }
11152 vertices[off+i].x = (nk_short) x;
11153 }
11154
11155 /* now load y coordinates */
11156 y=0;
11157 for (i=0; i < n; ++i) {
11158 flags = vertices[off+i].type;
11159 if (flags & 4) {
11160 nk_short dy = *points++;
11161 y += (flags & 32) ? dy : -dy; /* ??? */
11162 } else {
11163 if (!(flags & 32)) {
11164 y = y + (nk_short) (points[0]*256 + points[1]);
11165 points += 2;
11166 }
11167 }
11168 vertices[off+i].y = (nk_short) y;
11169 }
11170
11171 /* now convert them to our format */
11172 num_vertices=0;
11173 sx = sy = cx = cy = scx = scy = 0;
11174 for (i=0; i < n; ++i)
11175 {
11176 flags = vertices[off+i].type;
11177 x = (nk_short) vertices[off+i].x;
11178 y = (nk_short) vertices[off+i].y;
11179
11180 if (next_move == i) {
11181 if (i != 0)
11182 num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
11183
11184 /* now start the new one */
11185 start_off = !(flags & 1);
11186 if (start_off) {
11187 /* if we start off with an off-curve point, then when we need to find a point on the curve */
11188 /* where we can start, and we need to save some state for when we wraparound. */
11189 scx = x;
11190 scy = y;
11191 if (!(vertices[off+i+1].type & 1)) {
11192 /* next point is also a curve point, so interpolate an on-point curve */
11193 sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
11194 sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
11195 } else {
11196 /* otherwise just use the next point as our start point */
11197 sx = (nk_int) vertices[off+i+1].x;
11198 sy = (nk_int) vertices[off+i+1].y;
11199 ++i; /* we're using point i+1 as the starting point, so skip it */
11200 }
11201 } else {
11202 sx = x;
11203 sy = y;
11204 }
11205 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
11206 was_off = 0;
11207 next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
11208 ++j;
11209 } else {
11210 if (!(flags & 1))
11211 { /* if it's a curve */
11212 if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
11213 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
11214 cx = x;
11215 cy = y;
11216 was_off = 1;
11217 } else {
11218 if (was_off)
11219 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
11220 else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
11221 was_off = 0;
11222 }
11223 }
11224 }
11225 num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
11226 } else if (numberOfContours == -1) {
11227 /* Compound shapes. */
11228 int more = 1;
11229 const nk_byte *comp = data + g + 10;
11230 num_vertices = 0;
11231 vertices = 0;
11232
11233 while (more)
11234 {
11235 nk_ushort flags, gidx;
11236 int comp_num_verts = 0, i;
11237 struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
11238 float mtx[6] = {1,0,0,1,0,0}, m, n;
11239
11240 flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
11241 gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
11242
11243 if (flags & 2) { /* XY values */
11244 if (flags & 1) { /* shorts */
11245 mtx[4] = nk_ttSHORT(comp); comp+=2;
11246 mtx[5] = nk_ttSHORT(comp); comp+=2;
11247 } else {
11248 mtx[4] = nk_ttCHAR(comp); comp+=1;
11249 mtx[5] = nk_ttCHAR(comp); comp+=1;
11250 }
11251 } else {
11252 /* @TODO handle matching point */
11253 NK_ASSERT(0);
11254 }
11255 if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
11256 mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11257 mtx[1] = mtx[2] = 0;
11258 } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
11259 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11260 mtx[1] = mtx[2] = 0;
11261 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11262 } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
11263 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11264 mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11265 mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11266 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11267 }
11268
11269 /* Find transformation scales. */
11270 m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
11271 n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
11272
11273 /* Get indexed glyph. */
11274 comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
11275 if (comp_num_verts > 0)
11276 {
11277 /* Transform vertices. */
11278 for (i = 0; i < comp_num_verts; ++i) {
11279 struct nk_tt_vertex* v = &comp_verts[i];
11280 short x,y;
11281 x=v->x; y=v->y;
11282 v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
11283 v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
11284 x=v->cx; y=v->cy;
11285 v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
11286 v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
11287 }
11288 /* Append vertices. */
11289 tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
11290 (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
11291 if (!tmp) {
11292 if (vertices) alloc->free(alloc->userdata, vertices);
11293 if (comp_verts) alloc->free(alloc->userdata, comp_verts);
11294 return 0;
11295 }
11296 if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
11297 NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
11298 if (vertices) alloc->free(alloc->userdata,vertices);
11299 vertices = tmp;
11300 alloc->free(alloc->userdata,comp_verts);
11301 num_vertices += comp_num_verts;
11302 }
11303 /* More components ? */
11304 more = flags & (1<<5);
11305 }
11306 } else if (numberOfContours < 0) {
11307 /* @TODO other compound variations? */
11308 NK_ASSERT(0);
11309 } else {
11310 /* numberOfCounters == 0, do nothing */
11311 }
11312 *pvertices = vertices;
11313 return num_vertices;
11314}
11315NK_INTERN void
11316nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
11317 int *advanceWidth, int *leftSideBearing)
11318{
11319 nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
11320 if (glyph_index < numOfLongHorMetrics) {
11321 if (advanceWidth)
11322 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
11323 if (leftSideBearing)
11324 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
11325 } else {
11326 if (advanceWidth)
11327 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
11328 if (leftSideBearing)
11329 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
11330 }
11331}
11332NK_INTERN void
11333nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
11334 int *ascent, int *descent, int *lineGap)
11335{
11336 if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4);
11337 if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
11338 if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
11339}
11340NK_INTERN float
11341nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
11342{
11343 int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
11344 return (float) height / (float)fheight;
11345}
11346NK_INTERN float
11347nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
11348{
11349 int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
11350 return pixels / (float)unitsPerEm;
11351}
11352
11353/*-------------------------------------------------------------
11354 * antialiasing software rasterizer
11355 * --------------------------------------------------------------*/
11356NK_INTERN void
11357nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
11358 int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
11359 int *ix0, int *iy0, int *ix1, int *iy1)
11360{
11361 int x0,y0,x1,y1;
11362 if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
11363 /* e.g. space character */
11364 if (ix0) *ix0 = 0;
11365 if (iy0) *iy0 = 0;
11366 if (ix1) *ix1 = 0;
11367 if (iy1) *iy1 = 0;
11368 } else {
11369 /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
11370 if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
11371 if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
11372 if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
11373 if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
11374 }
11375}
11376NK_INTERN void
11377nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
11378 float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
11379{
11380 nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
11381}
11382
11383/*-------------------------------------------------------------
11384 * Rasterizer
11385 * --------------------------------------------------------------*/
11386NK_INTERN void*
11387nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
11388{
11389 if (hh->first_free) {
11390 void *p = hh->first_free;
11391 hh->first_free = * (void **) p;
11392 return p;
11393 } else {
11394 if (hh->num_remaining_in_head_chunk == 0) {
11395 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
11396 struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
11397 hh->alloc.alloc(hh->alloc.userdata, 0,
11398 sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
11399 if (c == 0) return 0;
11400 c->next = hh->head;
11401 hh->head = c;
11402 hh->num_remaining_in_head_chunk = count;
11403 }
11404 --hh->num_remaining_in_head_chunk;
11405 return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
11406 }
11407}
11408NK_INTERN void
11409nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
11410{
11411 *(void **) p = hh->first_free;
11412 hh->first_free = p;
11413}
11414NK_INTERN void
11415nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
11416{
11417 struct nk_tt__hheap_chunk *c = hh->head;
11418 while (c) {
11419 struct nk_tt__hheap_chunk *n = c->next;
11420 hh->alloc.free(hh->alloc.userdata, c);
11421 c = n;
11422 }
11423}
11424NK_INTERN struct nk_tt__active_edge*
11425nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
11426 int off_x, float start_point)
11427{
11428 struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
11429 nk_tt__hheap_alloc(hh, sizeof(*z));
11430 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
11431 /*STBTT_assert(e->y0 <= start_point); */
11432 if (!z) return z;
11433 z->fdx = dxdy;
11434 z->fdy = (dxdy != 0) ? (1/dxdy): 0;
11435 z->fx = e->x0 + dxdy * (start_point - e->y0);
11436 z->fx -= (float)off_x;
11437 z->direction = e->invert ? 1.0f : -1.0f;
11438 z->sy = e->y0;
11439 z->ey = e->y1;
11440 z->next = 0;
11441 return z;
11442}
11443NK_INTERN void
11444nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
11445 float x0, float y0, float x1, float y1)
11446{
11447 if (y0 == y1) return;
11448 NK_ASSERT(y0 < y1);
11449 NK_ASSERT(e->sy <= e->ey);
11450 if (y0 > e->ey) return;
11451 if (y1 < e->sy) return;
11452 if (y0 < e->sy) {
11453 x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
11454 y0 = e->sy;
11455 }
11456 if (y1 > e->ey) {
11457 x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
11458 y1 = e->ey;
11459 }
11460
11461 if (x0 == x) NK_ASSERT(x1 <= x+1);
11462 else if (x0 == x+1) NK_ASSERT(x1 >= x);
11463 else if (x0 <= x) NK_ASSERT(x1 <= x);
11464 else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
11465 else NK_ASSERT(x1 >= x && x1 <= x+1);
11466
11467 if (x0 <= x && x1 <= x)
11468 scanline[x] += e->direction * (y1-y0);
11469 else if (x0 >= x+1 && x1 >= x+1);
11470 else {
11471 NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
11472 /* coverage = 1 - average x position */
11473 scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
11474 }
11475}
11476NK_INTERN void
11477nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
11478 struct nk_tt__active_edge *e, float y_top)
11479{
11480 float y_bottom = y_top+1;
11481 while (e)
11482 {
11483 /* brute force every pixel */
11484 /* compute intersection points with top & bottom */
11485 NK_ASSERT(e->ey >= y_top);
11486 if (e->fdx == 0) {
11487 float x0 = e->fx;
11488 if (x0 < len) {
11489 if (x0 >= 0) {
11490 nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
11491 nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
11492 } else {
11493 nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
11494 }
11495 }
11496 } else {
11497 float x0 = e->fx;
11498 float dx = e->fdx;
11499 float xb = x0 + dx;
11500 float x_top, x_bottom;
11501 float y0,y1;
11502 float dy = e->fdy;
11503 NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
11504
11505 /* compute endpoints of line segment clipped to this scanline (if the */
11506 /* line segment starts on this scanline. x0 is the intersection of the */
11507 /* line with y_top, but that may be off the line segment. */
11508 if (e->sy > y_top) {
11509 x_top = x0 + dx * (e->sy - y_top);
11510 y0 = e->sy;
11511 } else {
11512 x_top = x0;
11513 y0 = y_top;
11514 }
11515
11516 if (e->ey < y_bottom) {
11517 x_bottom = x0 + dx * (e->ey - y_top);
11518 y1 = e->ey;
11519 } else {
11520 x_bottom = xb;
11521 y1 = y_bottom;
11522 }
11523
11524 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
11525 {
11526 /* from here on, we don't have to range check x values */
11527 if ((int) x_top == (int) x_bottom) {
11528 float height;
11529 /* simple case, only spans one pixel */
11530 int x = (int) x_top;
11531 height = y1 - y0;
11532 NK_ASSERT(x >= 0 && x < len);
11533 scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height;
11534 scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
11535 } else {
11536 int x,x1,x2;
11537 float y_crossing, step, sign, area;
11538 /* covers 2+ pixels */
11539 if (x_top > x_bottom)
11540 {
11541 /* flip scanline vertically; signed area is the same */
11542 float t;
11543 y0 = y_bottom - (y0 - y_top);
11544 y1 = y_bottom - (y1 - y_top);
11545 t = y0; y0 = y1; y1 = t;
11546 t = x_bottom; x_bottom = x_top; x_top = t;
11547 dx = -dx;
11548 dy = -dy;
11549 t = x0; x0 = xb; xb = t;
11550 }
11551
11552 x1 = (int) x_top;
11553 x2 = (int) x_bottom;
11554 /* compute intersection with y axis at x1+1 */
11555 y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
11556
11557 sign = e->direction;
11558 /* area of the rectangle covered from y0..y_crossing */
11559 area = sign * (y_crossing-y0);
11560 /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
11561 scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
11562
11563 step = sign * dy;
11564 for (x = x1+1; x < x2; ++x) {
11565 scanline[x] += area + step/2;
11566 area += step;
11567 }
11568 y_crossing += (float)dy * (float)(x2 - (x1+1));
11569
11570 scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
11571 scanline_fill[x2] += sign * (y1-y0);
11572 }
11573 }
11574 else
11575 {
11576 /* if edge goes outside of box we're drawing, we require */
11577 /* clipping logic. since this does not match the intended use */
11578 /* of this library, we use a different, very slow brute */
11579 /* force implementation */
11580 int x;
11581 for (x=0; x < len; ++x)
11582 {
11583 /* cases: */
11584 /* */
11585 /* there can be up to two intersections with the pixel. any intersection */
11586 /* with left or right edges can be handled by splitting into two (or three) */
11587 /* regions. intersections with top & bottom do not necessitate case-wise logic. */
11588 /* */
11589 /* the old way of doing this found the intersections with the left & right edges, */
11590 /* then used some simple logic to produce up to three segments in sorted order */
11591 /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
11592 /* across the x border, then the corresponding y position might not be distinct */
11593 /* from the other y segment, and it might ignored as an empty segment. to avoid */
11594 /* that, we need to explicitly produce segments based on x positions. */
11595
11596 /* rename variables to clear pairs */
11597 float ya = y_top;
11598 float x1 = (float) (x);
11599 float x2 = (float) (x+1);
11600 float x3 = xb;
11601 float y3 = y_bottom;
11602 float yb,y2;
11603
11604 yb = ((float)x - x0) / dx + y_top;
11605 y2 = ((float)x+1 - x0) / dx + y_top;
11606
11607 if (x0 < x1 && x3 > x2) { /* three segments descending down-right */
11608 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11609 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
11610 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11611 } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */
11612 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11613 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb);
11614 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11615 } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */
11616 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11617 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11618 } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */
11619 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11620 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11621 } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */
11622 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11623 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11624 } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */
11625 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11626 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11627 } else { /* one segment */
11628 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
11629 }
11630 }
11631 }
11632 }
11633 e = e->next;
11634 }
11635}
11636NK_INTERN void
11637nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
11638 int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
11639{
11640 /* directly AA rasterize edges w/o supersampling */
11641 struct nk_tt__hheap hh;
11642 struct nk_tt__active_edge *active = 0;
11643 int y,j=0, i;
11644 float scanline_data[129], *scanline, *scanline2;
11645
11646 NK_UNUSED(vsubsample);
11647 nk_zero_struct(hh);
11648 hh.alloc = *alloc;
11649
11650 if (result->w > 64)
11651 scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
11652 else scanline = scanline_data;
11653
11654 scanline2 = scanline + result->w;
11655 y = off_y;
11656 e[n].y0 = (float) (off_y + result->h) + 1;
11657
11658 while (j < result->h)
11659 {
11660 /* find center of pixel for this scanline */
11661 float scan_y_top = (float)y + 0.0f;
11662 float scan_y_bottom = (float)y + 1.0f;
11663 struct nk_tt__active_edge **step = &active;
11664
11665 NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
11666 NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
11667
11668 /* update all active edges; */
11669 /* remove all active edges that terminate before the top of this scanline */
11670 while (*step) {
11671 struct nk_tt__active_edge * z = *step;
11672 if (z->ey <= scan_y_top) {
11673 *step = z->next; /* delete from list */
11674 NK_ASSERT(z->direction);
11675 z->direction = 0;
11676 nk_tt__hheap_free(&hh, z);
11677 } else {
11678 step = &((*step)->next); /* advance through list */
11679 }
11680 }
11681
11682 /* insert all edges that start before the bottom of this scanline */
11683 while (e->y0 <= scan_y_bottom) {
11684 if (e->y0 != e->y1) {
11685 struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
11686 if (z != 0) {
11687 NK_ASSERT(z->ey >= scan_y_top);
11688 /* insert at front */
11689 z->next = active;
11690 active = z;
11691 }
11692 }
11693 ++e;
11694 }
11695
11696 /* now process all active edges */
11697 if (active)
11698 nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
11699
11700 {
11701 float sum = 0;
11702 for (i=0; i < result->w; ++i) {
11703 float k;
11704 int m;
11705 sum += scanline2[i];
11706 k = scanline[i] + sum;
11707 k = (float) NK_ABS(k) * 255.0f + 0.5f;
11708 m = (int) k;
11709 if (m > 255) m = 255;
11710 result->pixels[j*result->stride + i] = (unsigned char) m;
11711 }
11712 }
11713 /* advance all the edges */
11714 step = &active;
11715 while (*step) {
11716 struct nk_tt__active_edge *z = *step;
11717 z->fx += z->fdx; /* advance to position for current scanline */
11718 step = &((*step)->next); /* advance through list */
11719 }
11720 ++y;
11721 ++j;
11722 }
11723 nk_tt__hheap_cleanup(&hh);
11724 if (scanline != scanline_data)
11725 alloc->free(alloc->userdata, scanline);
11726}
11727NK_INTERN void
11728nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
11729{
11730 int i,j;
11731 #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0)
11732 for (i=1; i < n; ++i) {
11733 struct nk_tt__edge t = p[i], *a = &t;
11734 j = i;
11735 while (j > 0) {
11736 struct nk_tt__edge *b = &p[j-1];
11737 int c = NK_TT__COMPARE(a,b);
11738 if (!c) break;
11739 p[j] = p[j-1];
11740 --j;
11741 }
11742 if (i != j)
11743 p[j] = t;
11744 }
11745}
11746NK_INTERN void
11747nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
11748{
11749 /* threshold for transitioning to insertion sort */
11750 while (n > 12) {
11751 struct nk_tt__edge t;
11752 int c01,c12,c,m,i,j;
11753
11754 /* compute median of three */
11755 m = n >> 1;
11756 c01 = NK_TT__COMPARE(&p[0],&p[m]);
11757 c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
11758
11759 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
11760 if (c01 != c12) {
11761 /* otherwise, we'll need to swap something else to middle */
11762 int z;
11763 c = NK_TT__COMPARE(&p[0],&p[n-1]);
11764 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
11765 /* 0<mid && mid>n: 0>n => 0; 0<n => n */
11766 z = (c == c12) ? 0 : n-1;
11767 t = p[z];
11768 p[z] = p[m];
11769 p[m] = t;
11770 }
11771
11772 /* now p[m] is the median-of-three */
11773 /* swap it to the beginning so it won't move around */
11774 t = p[0];
11775 p[0] = p[m];
11776 p[m] = t;
11777
11778 /* partition loop */
11779 i=1;
11780 j=n-1;
11781 for(;;) {
11782 /* handling of equality is crucial here */
11783 /* for sentinels & efficiency with duplicates */
11784 for (;;++i) {
11785 if (!NK_TT__COMPARE(&p[i], &p[0])) break;
11786 }
11787 for (;;--j) {
11788 if (!NK_TT__COMPARE(&p[0], &p[j])) break;
11789 }
11790
11791 /* make sure we haven't crossed */
11792 if (i >= j) break;
11793 t = p[i];
11794 p[i] = p[j];
11795 p[j] = t;
11796
11797 ++i;
11798 --j;
11799
11800 }
11801
11802 /* recurse on smaller side, iterate on larger */
11803 if (j < (n-i)) {
11804 nk_tt__sort_edges_quicksort(p,j);
11805 p = p+i;
11806 n = n-i;
11807 } else {
11808 nk_tt__sort_edges_quicksort(p+i, n-i);
11809 n = j;
11810 }
11811 }
11812}
11813NK_INTERN void
11814nk_tt__sort_edges(struct nk_tt__edge *p, int n)
11815{
11816 nk_tt__sort_edges_quicksort(p, n);
11817 nk_tt__sort_edges_ins_sort(p, n);
11818}
11819NK_INTERN void
11820nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
11821 int *wcount, int windings, float scale_x, float scale_y,
11822 float shift_x, float shift_y, int off_x, int off_y, int invert,
11823 struct nk_allocator *alloc)
11824{
11825 float y_scale_inv = invert ? -scale_y : scale_y;
11826 struct nk_tt__edge *e;
11827 int n,i,j,k,m;
11828 int vsubsample = 1;
11829 /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
11830
11831 /* now we have to blow out the windings into explicit edge lists */
11832 n = 0;
11833 for (i=0; i < windings; ++i)
11834 n += wcount[i];
11835
11836 e = (struct nk_tt__edge*)
11837 alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
11838 if (e == 0) return;
11839 n = 0;
11840
11841 m=0;
11842 for (i=0; i < windings; ++i)
11843 {
11844 struct nk_tt__point *p = pts + m;
11845 m += wcount[i];
11846 j = wcount[i]-1;
11847 for (k=0; k < wcount[i]; j=k++) {
11848 int a=k,b=j;
11849 /* skip the edge if horizontal */
11850 if (p[j].y == p[k].y)
11851 continue;
11852
11853 /* add edge from j to k to the list */
11854 e[n].invert = 0;
11855 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
11856 e[n].invert = 1;
11857 a=j,b=k;
11858 }
11859 e[n].x0 = p[a].x * scale_x + shift_x;
11860 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
11861 e[n].x1 = p[b].x * scale_x + shift_x;
11862 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
11863 ++n;
11864 }
11865 }
11866
11867 /* now sort the edges by their highest point (should snap to integer, and then by x) */
11868 /*STBTT_sort(e, n, sizeof(e[0]), nk_tt__edge_compare); */
11869 nk_tt__sort_edges(e, n);
11870 /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
11871 nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
11872 alloc->free(alloc->userdata, e);
11873}
11874NK_INTERN void
11875nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
11876{
11877 if (!points) return; /* during first pass, it's unallocated */
11878 points[n].x = x;
11879 points[n].y = y;
11880}
11881NK_INTERN int
11882nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
11883 float x0, float y0, float x1, float y1, float x2, float y2,
11884 float objspace_flatness_squared, int n)
11885{
11886 /* tesselate until threshold p is happy...
11887 * @TODO warped to compensate for non-linear stretching */
11888 /* midpoint */
11889 float mx = (x0 + 2*x1 + x2)/4;
11890 float my = (y0 + 2*y1 + y2)/4;
11891 /* versus directly drawn line */
11892 float dx = (x0+x2)/2 - mx;
11893 float dy = (y0+y2)/2 - my;
11894 if (n > 16) /* 65536 segments on one curve better be enough! */
11895 return 1;
11896
11897 /* half-pixel error allowed... need to be smaller if AA */
11898 if (dx*dx+dy*dy > objspace_flatness_squared) {
11899 nk_tt__tesselate_curve(points, num_points, x0,y0,
11900 (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
11901 nk_tt__tesselate_curve(points, num_points, mx,my,
11902 (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
11903 } else {
11904 nk_tt__add_point(points, *num_points,x2,y2);
11905 *num_points = *num_points+1;
11906 }
11907 return 1;
11908}
11909NK_INTERN struct nk_tt__point*
11910nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
11911 float objspace_flatness, int **contour_lengths, int *num_contours,
11912 struct nk_allocator *alloc)
11913{
11914 /* returns number of contours */
11915 struct nk_tt__point *points=0;
11916 int num_points=0;
11917 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
11918 int i;
11919 int n=0;
11920 int start=0;
11921 int pass;
11922
11923 /* count how many "moves" there are to get the contour count */
11924 for (i=0; i < num_verts; ++i)
11925 if (vertices[i].type == NK_TT_vmove) ++n;
11926
11927 *num_contours = n;
11928 if (n == 0) return 0;
11929
11930 *contour_lengths = (int *)
11931 alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
11932 if (*contour_lengths == 0) {
11933 *num_contours = 0;
11934 return 0;
11935 }
11936
11937 /* make two passes through the points so we don't need to realloc */
11938 for (pass=0; pass < 2; ++pass)
11939 {
11940 float x=0,y=0;
11941 if (pass == 1) {
11942 points = (struct nk_tt__point *)
11943 alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
11944 if (points == 0) goto error;
11945 }
11946 num_points = 0;
11947 n= -1;
11948
11949 for (i=0; i < num_verts; ++i)
11950 {
11951 switch (vertices[i].type) {
11952 case NK_TT_vmove:
11953 /* start the next contour */
11954 if (n >= 0)
11955 (*contour_lengths)[n] = num_points - start;
11956 ++n;
11957 start = num_points;
11958
11959 x = vertices[i].x, y = vertices[i].y;
11960 nk_tt__add_point(points, num_points++, x,y);
11961 break;
11962 case NK_TT_vline:
11963 x = vertices[i].x, y = vertices[i].y;
11964 nk_tt__add_point(points, num_points++, x, y);
11965 break;
11966 case NK_TT_vcurve:
11967 nk_tt__tesselate_curve(points, &num_points, x,y,
11968 vertices[i].cx, vertices[i].cy,
11969 vertices[i].x, vertices[i].y,
11970 objspace_flatness_squared, 0);
11971 x = vertices[i].x, y = vertices[i].y;
11972 break;
11973 default: break;
11974 }
11975 }
11976 (*contour_lengths)[n] = num_points - start;
11977 }
11978 return points;
11979
11980error:
11981 alloc->free(alloc->userdata, points);
11982 alloc->free(alloc->userdata, *contour_lengths);
11983 *contour_lengths = 0;
11984 *num_contours = 0;
11985 return 0;
11986}
11987NK_INTERN void
11988nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
11989 struct nk_tt_vertex *vertices, int num_verts,
11990 float scale_x, float scale_y, float shift_x, float shift_y,
11991 int x_off, int y_off, int invert, struct nk_allocator *alloc)
11992{
11993 float scale = scale_x > scale_y ? scale_y : scale_x;
11994 int winding_count, *winding_lengths;
11995 struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
11996 flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
11997
11998 NK_ASSERT(alloc);
11999 if (windings) {
12000 nk_tt__rasterize(result, windings, winding_lengths, winding_count,
12001 scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
12002 alloc->free(alloc->userdata, winding_lengths);
12003 alloc->free(alloc->userdata, windings);
12004 }
12005}
12006NK_INTERN void
12007nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
12008 int out_w, int out_h, int out_stride, float scale_x, float scale_y,
12009 float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
12010{
12011 int ix0,iy0;
12012 struct nk_tt_vertex *vertices;
12013 int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
12014 struct nk_tt__bitmap gbm;
12015
12016 nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
12017 shift_y, &ix0,&iy0,0,0);
12018 gbm.pixels = output;
12019 gbm.w = out_w;
12020 gbm.h = out_h;
12021 gbm.stride = out_stride;
12022
12023 if (gbm.w && gbm.h)
12024 nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
12025 shift_x, shift_y, ix0,iy0, 1, alloc);
12026 alloc->free(alloc->userdata, vertices);
12027}
12028
12029/*-------------------------------------------------------------
12030 * Bitmap baking
12031 * --------------------------------------------------------------*/
12032NK_INTERN int
12033nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
12034 int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
12035{
12036 int num_nodes = pw - padding;
12037 struct nk_rp_context *context = (struct nk_rp_context *)
12038 alloc->alloc(alloc->userdata,0, sizeof(*context));
12039 struct nk_rp_node *nodes = (struct nk_rp_node*)
12040 alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes));
12041
12042 if (context == 0 || nodes == 0) {
12043 if (context != 0) alloc->free(alloc->userdata, context);
12044 if (nodes != 0) alloc->free(alloc->userdata, nodes);
12045 return 0;
12046 }
12047
12048 spc->width = pw;
12049 spc->height = ph;
12050 spc->pixels = pixels;
12051 spc->pack_info = context;
12052 spc->nodes = nodes;
12053 spc->padding = padding;
12054 spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
12055 spc->h_oversample = 1;
12056 spc->v_oversample = 1;
12057
12058 nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
12059 if (pixels)
12060 NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
12061 return 1;
12062}
12063NK_INTERN void
12064nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
12065{
12066 alloc->free(alloc->userdata, spc->nodes);
12067 alloc->free(alloc->userdata, spc->pack_info);
12068}
12069NK_INTERN void
12070nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
12071 unsigned int h_oversample, unsigned int v_oversample)
12072{
12073 NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
12074 NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
12075 if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
12076 spc->h_oversample = h_oversample;
12077 if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
12078 spc->v_oversample = v_oversample;
12079}
12080NK_INTERN void
12081nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
12082 int kernel_width)
12083{
12084 unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
12085 int safe_w = w - kernel_width;
12086 int j;
12087
12088 for (j=0; j < h; ++j)
12089 {
12090 int i;
12091 unsigned int total;
12092 NK_MEMSET(buffer, 0, (nk_size)kernel_width);
12093
12094 total = 0;
12095
12096 /* make kernel_width a constant in common cases so compiler can optimize out the divide */
12097 switch (kernel_width) {
12098 case 2:
12099 for (i=0; i <= safe_w; ++i) {
12100 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12101 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12102 pixels[i] = (unsigned char) (total / 2);
12103 }
12104 break;
12105 case 3:
12106 for (i=0; i <= safe_w; ++i) {
12107 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12108 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12109 pixels[i] = (unsigned char) (total / 3);
12110 }
12111 break;
12112 case 4:
12113 for (i=0; i <= safe_w; ++i) {
12114 total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK];
12115 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12116 pixels[i] = (unsigned char) (total / 4);
12117 }
12118 break;
12119 case 5:
12120 for (i=0; i <= safe_w; ++i) {
12121 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12122 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12123 pixels[i] = (unsigned char) (total / 5);
12124 }
12125 break;
12126 default:
12127 for (i=0; i <= safe_w; ++i) {
12128 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12129 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12130 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
12131 }
12132 break;
12133 }
12134
12135 for (; i < w; ++i) {
12136 NK_ASSERT(pixels[i] == 0);
12137 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
12138 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
12139 }
12140 pixels += stride_in_bytes;
12141 }
12142}
12143NK_INTERN void
12144nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
12145 int kernel_width)
12146{
12147 unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
12148 int safe_h = h - kernel_width;
12149 int j;
12150
12151 for (j=0; j < w; ++j)
12152 {
12153 int i;
12154 unsigned int total;
12155 NK_MEMSET(buffer, 0, (nk_size)kernel_width);
12156
12157 total = 0;
12158
12159 /* make kernel_width a constant in common cases so compiler can optimize out the divide */
12160 switch (kernel_width) {
12161 case 2:
12162 for (i=0; i <= safe_h; ++i) {
12163 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12164 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12165 pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
12166 }
12167 break;
12168 case 3:
12169 for (i=0; i <= safe_h; ++i) {
12170 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12171 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12172 pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
12173 }
12174 break;
12175 case 4:
12176 for (i=0; i <= safe_h; ++i) {
12177 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12178 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12179 pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
12180 }
12181 break;
12182 case 5:
12183 for (i=0; i <= safe_h; ++i) {
12184 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12185 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12186 pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
12187 }
12188 break;
12189 default:
12190 for (i=0; i <= safe_h; ++i) {
12191 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12192 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12193 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
12194 }
12195 break;
12196 }
12197
12198 for (; i < h; ++i) {
12199 NK_ASSERT(pixels[i*stride_in_bytes] == 0);
12200 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
12201 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
12202 }
12203 pixels += 1;
12204 }
12205}
12206NK_INTERN float
12207nk_tt__oversample_shift(int oversample)
12208{
12209 if (!oversample)
12210 return 0.0f;
12211
12212 /* The prefilter is a box filter of width "oversample", */
12213 /* which shifts phase by (oversample - 1)/2 pixels in */
12214 /* oversampled space. We want to shift in the opposite */
12215 /* direction to counter this. */
12216 return (float)-(oversample - 1) / (2.0f * (float)oversample);
12217}
12218NK_INTERN int
12219nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
12220 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
12221 int num_ranges, struct nk_rp_rect *rects)
12222{
12223 /* rects array must be big enough to accommodate all characters in the given ranges */
12224 int i,j,k;
12225 k = 0;
12226
12227 for (i=0; i < num_ranges; ++i) {
12228 float fh = ranges[i].font_size;
12229 float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
12230 nk_tt_ScaleForMappingEmToPixels(info, -fh);
12231 ranges[i].h_oversample = (unsigned char) spc->h_oversample;
12232 ranges[i].v_oversample = (unsigned char) spc->v_oversample;
12233 for (j=0; j < ranges[i].num_chars; ++j) {
12234 int x0,y0,x1,y1;
12235 int codepoint = ranges[i].first_unicode_codepoint_in_range ?
12236 ranges[i].first_unicode_codepoint_in_range + j :
12237 ranges[i].array_of_unicode_codepoints[j];
12238
12239 int glyph = nk_tt_FindGlyphIndex(info, codepoint);
12240 nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
12241 scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
12242 rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
12243 rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
12244 ++k;
12245 }
12246 }
12247 return k;
12248}
12249NK_INTERN int
12250nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
12251 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
12252 int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
12253{
12254 int i,j,k, return_value = 1;
12255 /* save current values */
12256 int old_h_over = (int)spc->h_oversample;
12257 int old_v_over = (int)spc->v_oversample;
12258 /* rects array must be big enough to accommodate all characters in the given ranges */
12259
12260 k = 0;
12261 for (i=0; i < num_ranges; ++i)
12262 {
12263 float fh = ranges[i].font_size;
12264 float recip_h,recip_v,sub_x,sub_y;
12265 float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
12266 nk_tt_ScaleForMappingEmToPixels(info, -fh);
12267
12268 spc->h_oversample = ranges[i].h_oversample;
12269 spc->v_oversample = ranges[i].v_oversample;
12270
12271 recip_h = 1.0f / (float)spc->h_oversample;
12272 recip_v = 1.0f / (float)spc->v_oversample;
12273
12274 sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
12275 sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
12276
12277 for (j=0; j < ranges[i].num_chars; ++j)
12278 {
12279 struct nk_rp_rect *r = &rects[k];
12280 if (r->was_packed)
12281 {
12282 struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
12283 int advance, lsb, x0,y0,x1,y1;
12284 int codepoint = ranges[i].first_unicode_codepoint_in_range ?
12285 ranges[i].first_unicode_codepoint_in_range + j :
12286 ranges[i].array_of_unicode_codepoints[j];
12287 int glyph = nk_tt_FindGlyphIndex(info, codepoint);
12288 nk_rp_coord pad = (nk_rp_coord) spc->padding;
12289
12290 /* pad on left and top */
12291 r->x = (nk_rp_coord)((int)r->x + (int)pad);
12292 r->y = (nk_rp_coord)((int)r->y + (int)pad);
12293 r->w = (nk_rp_coord)((int)r->w - (int)pad);
12294 r->h = (nk_rp_coord)((int)r->h - (int)pad);
12295
12296 nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
12297 nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
12298 (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
12299 nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
12300 (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
12301 spc->stride_in_bytes, scale * (float)spc->h_oversample,
12302 scale * (float)spc->v_oversample, 0,0, glyph, alloc);
12303
12304 if (spc->h_oversample > 1)
12305 nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
12306 r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
12307
12308 if (spc->v_oversample > 1)
12309 nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
12310 r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
12311
12312 bc->x0 = (nk_ushort) r->x;
12313 bc->y0 = (nk_ushort) r->y;
12314 bc->x1 = (nk_ushort) (r->x + r->w);
12315 bc->y1 = (nk_ushort) (r->y + r->h);
12316 bc->xadvance = scale * (float)advance;
12317 bc->xoff = (float) x0 * recip_h + sub_x;
12318 bc->yoff = (float) y0 * recip_v + sub_y;
12319 bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x;
12320 bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y;
12321 } else {
12322 return_value = 0; /* if any fail, report failure */
12323 }
12324 ++k;
12325 }
12326 }
12327 /* restore original values */
12328 spc->h_oversample = (unsigned int)old_h_over;
12329 spc->v_oversample = (unsigned int)old_v_over;
12330 return return_value;
12331}
12332NK_INTERN void
12333nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
12334 int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
12335 int align_to_integer)
12336{
12337 float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
12338 struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
12339 if (align_to_integer) {
12340 int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
12341 int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
12342
12343 float x = (float)tx;
12344 float y = (float)ty;
12345
12346 q->x0 = x;
12347 q->y0 = y;
12348 q->x1 = x + b->xoff2 - b->xoff;
12349 q->y1 = y + b->yoff2 - b->yoff;
12350 } else {
12351 q->x0 = *xpos + b->xoff;
12352 q->y0 = *ypos + b->yoff;
12353 q->x1 = *xpos + b->xoff2;
12354 q->y1 = *ypos + b->yoff2;
12355 }
12356 q->s0 = b->x0 * ipw;
12357 q->t0 = b->y0 * iph;
12358 q->s1 = b->x1 * ipw;
12359 q->t1 = b->y1 * iph;
12360 *xpos += b->xadvance;
12361}
12362
12363/* -------------------------------------------------------------
12364 *
12365 * FONT BAKING
12366 *
12367 * --------------------------------------------------------------*/
12368struct nk_font_bake_data {
12369 struct nk_tt_fontinfo info;
12370 struct nk_rp_rect *rects;
12371 struct nk_tt_pack_range *ranges;
12372 nk_rune range_count;
12373};
12374
12375struct nk_font_baker {
12376 struct nk_allocator alloc;
12377 struct nk_tt_pack_context spc;
12378 struct nk_font_bake_data *build;
12379 struct nk_tt_packedchar *packed_chars;
12380 struct nk_rp_rect *rects;
12381 struct nk_tt_pack_range *ranges;
12382};
12383
12384NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
12385NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
12386NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
12387NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
12388NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
12389
12390NK_INTERN int
12391nk_range_count(const nk_rune *range)
12392{
12393 const nk_rune *iter = range;
12394 NK_ASSERT(range);
12395 if (!range) return 0;
12396 while (*(iter++) != 0);
12397 return (iter == range) ? 0 : (int)((iter - range)/2);
12398}
12399NK_INTERN int
12400nk_range_glyph_count(const nk_rune *range, int count)
12401{
12402 int i = 0;
12403 int total_glyphs = 0;
12404 for (i = 0; i < count; ++i) {
12405 int diff;
12406 nk_rune f = range[(i*2)+0];
12407 nk_rune t = range[(i*2)+1];
12408 NK_ASSERT(t >= f);
12409 diff = (int)((t - f) + 1);
12410 total_glyphs += diff;
12411 }
12412 return total_glyphs;
12413}
12414NK_API const nk_rune*
12415nk_font_default_glyph_ranges(void)
12416{
12417 NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
12418 return ranges;
12419}
12420NK_API const nk_rune*
12421nk_font_chinese_glyph_ranges(void)
12422{
12423 NK_STORAGE const nk_rune ranges[] = {
12424 0x0020, 0x00FF,
12425 0x3000, 0x30FF,
12426 0x31F0, 0x31FF,
12427 0xFF00, 0xFFEF,
12428 0x4e00, 0x9FAF,
12429 0
12430 };
12431 return ranges;
12432}
12433NK_API const nk_rune*
12434nk_font_cyrillic_glyph_ranges(void)
12435{
12436 NK_STORAGE const nk_rune ranges[] = {
12437 0x0020, 0x00FF,
12438 0x0400, 0x052F,
12439 0x2DE0, 0x2DFF,
12440 0xA640, 0xA69F,
12441 0
12442 };
12443 return ranges;
12444}
12445NK_API const nk_rune*
12446nk_font_korean_glyph_ranges(void)
12447{
12448 NK_STORAGE const nk_rune ranges[] = {
12449 0x0020, 0x00FF,
12450 0x3131, 0x3163,
12451 0xAC00, 0xD79D,
12452 0
12453 };
12454 return ranges;
12455}
12456NK_INTERN void
12457nk_font_baker_memory(nk_size *temp, int *glyph_count,
12458 struct nk_font_config *config_list, int count)
12459{
12460 int range_count = 0;
12461 int total_range_count = 0;
12462 struct nk_font_config *iter, *i;
12463
12464 NK_ASSERT(config_list);
12465 NK_ASSERT(glyph_count);
12466 if (!config_list) {
12467 *temp = 0;
12468 *glyph_count = 0;
12469 return;
12470 }
12471 *glyph_count = 0;
12472 for (iter = config_list; iter; iter = iter->next) {
12473 i = iter;
12474 do {if (!i->range) iter->range = nk_font_default_glyph_ranges();
12475 range_count = nk_range_count(i->range);
12476 total_range_count += range_count;
12477 *glyph_count += nk_range_glyph_count(i->range, range_count);
12478 } while ((i = i->n) != iter);
12479 }
12480 *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
12481 *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
12482 *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
12483 *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
12484 *temp += sizeof(struct nk_font_baker);
12485 *temp += nk_rect_align + nk_range_align + nk_char_align;
12486 *temp += nk_build_align + nk_baker_align;
12487}
12488NK_INTERN struct nk_font_baker*
12489nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
12490{
12491 struct nk_font_baker *baker;
12492 if (!memory) return 0;
12493 /* setup baker inside a memory block */
12494 baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
12495 baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
12496 baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
12497 baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
12498 baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
12499 baker->alloc = *alloc;
12500 return baker;
12501}
12502NK_INTERN int
12503nk_font_bake_pack(struct nk_font_baker *baker,
12504 nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
12505 const struct nk_font_config *config_list, int count,
12506 struct nk_allocator *alloc)
12507{
12508 NK_STORAGE const nk_size max_height = 1024 * 32;
12509 const struct nk_font_config *config_iter, *it;
12510 int total_glyph_count = 0;
12511 int total_range_count = 0;
12512 int range_count = 0;
12513 int i = 0;
12514
12515 NK_ASSERT(image_memory);
12516 NK_ASSERT(width);
12517 NK_ASSERT(height);
12518 NK_ASSERT(config_list);
12519 NK_ASSERT(count);
12520 NK_ASSERT(alloc);
12521
12522 if (!image_memory || !width || !height || !config_list || !count) return nk_false;
12523 for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
12524 it = config_iter;
12525 do {range_count = nk_range_count(it->range);
12526 total_range_count += range_count;
12527 total_glyph_count += nk_range_glyph_count(it->range, range_count);
12528 } while ((it = it->n) != config_iter);
12529 }
12530 /* setup font baker from temporary memory */
12531 for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
12532 it = config_iter;
12533 do {if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)it->ttf_blob, 0))
12534 return nk_false;
12535 } while ((it = it->n) != config_iter);
12536 }
12537 *height = 0;
12538 *width = (total_glyph_count > 1000) ? 1024 : 512;
12539 nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
12540 {
12541 int input_i = 0;
12542 int range_n = 0;
12543 int rect_n = 0;
12544 int char_n = 0;
12545
12546 if (custom) {
12547 /* pack custom user data first so it will be in the upper left corner*/
12548 struct nk_rp_rect custom_space;
12549 nk_zero(&custom_space, sizeof(custom_space));
12550 custom_space.w = (nk_rp_coord)(custom->w);
12551 custom_space.h = (nk_rp_coord)(custom->h);
12552
12553 nk_tt_PackSetOversampling(&baker->spc, 1, 1);
12554 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
12555 *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
12556
12557 custom->x = (short)custom_space.x;
12558 custom->y = (short)custom_space.y;
12559 custom->w = (short)custom_space.w;
12560 custom->h = (short)custom_space.h;
12561 }
12562
12563 /* first font pass: pack all glyphs */
12564 for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
12565 config_iter = config_iter->next) {
12566 it = config_iter;
12567 do {int n = 0;
12568 int glyph_count;
12569 const nk_rune *in_range;
12570 const struct nk_font_config *cfg = it;
12571 struct nk_font_bake_data *tmp = &baker->build[input_i++];
12572
12573 /* count glyphs + ranges in current font */
12574 glyph_count = 0; range_count = 0;
12575 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
12576 glyph_count += (int)(in_range[1] - in_range[0]) + 1;
12577 range_count++;
12578 }
12579
12580 /* setup ranges */
12581 tmp->ranges = baker->ranges + range_n;
12582 tmp->range_count = (nk_rune)range_count;
12583 range_n += range_count;
12584 for (i = 0; i < range_count; ++i) {
12585 in_range = &cfg->range[i * 2];
12586 tmp->ranges[i].font_size = cfg->size;
12587 tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
12588 tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
12589 tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
12590 char_n += tmp->ranges[i].num_chars;
12591 }
12592
12593 /* pack */
12594 tmp->rects = baker->rects + rect_n;
12595 rect_n += glyph_count;
12596 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
12597 n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
12598 tmp->ranges, (int)tmp->range_count, tmp->rects);
12599 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
12600
12601 /* texture height */
12602 for (i = 0; i < n; ++i) {
12603 if (tmp->rects[i].was_packed)
12604 *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
12605 }
12606 } while ((it = it->n) != config_iter);
12607 }
12608 NK_ASSERT(rect_n == total_glyph_count);
12609 NK_ASSERT(char_n == total_glyph_count);
12610 NK_ASSERT(range_n == total_range_count);
12611 }
12612 *height = (int)nk_round_up_pow2((nk_uint)*height);
12613 *image_memory = (nk_size)(*width) * (nk_size)(*height);
12614 return nk_true;
12615}
12616NK_INTERN void
12617nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
12618 struct nk_font_glyph *glyphs, int glyphs_count,
12619 const struct nk_font_config *config_list, int font_count)
12620{
12621 int input_i = 0;
12622 nk_rune glyph_n = 0;
12623 const struct nk_font_config *config_iter;
12624 const struct nk_font_config *it;
12625
12626 NK_ASSERT(image_memory);
12627 NK_ASSERT(width);
12628 NK_ASSERT(height);
12629 NK_ASSERT(config_list);
12630 NK_ASSERT(baker);
12631 NK_ASSERT(font_count);
12632 NK_ASSERT(glyphs_count);
12633 if (!image_memory || !width || !height || !config_list ||
12634 !font_count || !glyphs || !glyphs_count)
12635 return;
12636
12637 /* second font pass: render glyphs */
12638 nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
12639 baker->spc.pixels = (unsigned char*)image_memory;
12640 baker->spc.height = (int)height;
12641 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
12642 config_iter = config_iter->next) {
12643 it = config_iter;
12644 do {const struct nk_font_config *cfg = it;
12645 struct nk_font_bake_data *tmp = &baker->build[input_i++];
12646 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
12647 nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
12648 (int)tmp->range_count, tmp->rects, &baker->alloc);
12649 } while ((it = it->n) != config_iter);
12650 } nk_tt_PackEnd(&baker->spc, &baker->alloc);
12651
12652 /* third pass: setup font and glyphs */
12653 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
12654 config_iter = config_iter->next) {
12655 it = config_iter;
12656 do {nk_size i = 0;
12657 int char_idx = 0;
12658 nk_rune glyph_count = 0;
12659 const struct nk_font_config *cfg = it;
12660 struct nk_font_bake_data *tmp = &baker->build[input_i++];
12661 struct nk_baked_font *dst_font = cfg->font;
12662
12663 float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
12664 int unscaled_ascent, unscaled_descent, unscaled_line_gap;
12665 nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
12666 &unscaled_line_gap);
12667
12668 /* fill baked font */
12669 if (!cfg->merge_mode) {
12670 dst_font->ranges = cfg->range;
12671 dst_font->height = cfg->size;
12672 dst_font->ascent = ((float)unscaled_ascent * font_scale);
12673 dst_font->descent = ((float)unscaled_descent * font_scale);
12674 dst_font->glyph_offset = glyph_n;
12675 // Need to zero this, or it will carry over from a previous
12676 // bake, and cause a segfault when accessing glyphs[].
12677 dst_font->glyph_count = 0;
12678 }
12679
12680 /* fill own baked font glyph array */
12681 for (i = 0; i < tmp->range_count; ++i) {
12682 struct nk_tt_pack_range *range = &tmp->ranges[i];
12683 for (char_idx = 0; char_idx < range->num_chars; char_idx++)
12684 {
12685 nk_rune codepoint = 0;
12686 float dummy_x = 0, dummy_y = 0;
12687 struct nk_tt_aligned_quad q;
12688 struct nk_font_glyph *glyph;
12689
12690 /* query glyph bounds from stb_truetype */
12691 const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
12692 if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
12693 codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
12694 nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
12695 (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
12696
12697 /* fill own glyph type with data */
12698 glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count];
12699 glyph->codepoint = codepoint;
12700 glyph->x0 = q.x0; glyph->y0 = q.y0;
12701 glyph->x1 = q.x1; glyph->y1 = q.y1;
12702 glyph->y0 += (dst_font->ascent + 0.5f);
12703 glyph->y1 += (dst_font->ascent + 0.5f);
12704 glyph->w = glyph->x1 - glyph->x0 + 0.5f;
12705 glyph->h = glyph->y1 - glyph->y0;
12706
12707 if (cfg->coord_type == NK_COORD_PIXEL) {
12708 glyph->u0 = q.s0 * (float)width;
12709 glyph->v0 = q.t0 * (float)height;
12710 glyph->u1 = q.s1 * (float)width;
12711 glyph->v1 = q.t1 * (float)height;
12712 } else {
12713 glyph->u0 = q.s0;
12714 glyph->v0 = q.t0;
12715 glyph->u1 = q.s1;
12716 glyph->v1 = q.t1;
12717 }
12718 glyph->xadvance = (pc->xadvance + cfg->spacing.x);
12719 if (cfg->pixel_snap)
12720 glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
12721 glyph_count++;
12722 }
12723 }
12724 dst_font->glyph_count += glyph_count;
12725 glyph_n += glyph_count;
12726 } while ((it = it->n) != config_iter);
12727 }
12728}
12729NK_INTERN void
12730nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
12731 struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
12732 int tex_height, char white, char black)
12733{
12734 nk_byte *pixels;
12735 int y = 0;
12736 int x = 0;
12737 int n = 0;
12738
12739 NK_ASSERT(img_memory);
12740 NK_ASSERT(img_width);
12741 NK_ASSERT(img_height);
12742 NK_ASSERT(texture_data_mask);
12743 NK_UNUSED(tex_height);
12744 if (!img_memory || !img_width || !img_height || !texture_data_mask)
12745 return;
12746
12747 pixels = (nk_byte*)img_memory;
12748 for (y = 0, n = 0; y < tex_height; ++y) {
12749 for (x = 0; x < tex_width; ++x, ++n) {
12750 const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
12751 const int off1 = off0 + 1 + tex_width;
12752 pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
12753 pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
12754 }
12755 }
12756}
12757NK_INTERN void
12758nk_font_bake_convert(void *out_memory, int img_width, int img_height,
12759 const void *in_memory)
12760{
12761 int n = 0;
12762 nk_rune *dst;
12763 const nk_byte *src;
12764
12765 NK_ASSERT(out_memory);
12766 NK_ASSERT(in_memory);
12767 NK_ASSERT(img_width);
12768 NK_ASSERT(img_height);
12769 if (!out_memory || !in_memory || !img_height || !img_width) return;
12770
12771 dst = (nk_rune*)out_memory;
12772 src = (const nk_byte*)in_memory;
12773 for (n = (int)(img_width * img_height); n > 0; n--)
12774 *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
12775}
12776
12777/* -------------------------------------------------------------
12778 *
12779 * FONT
12780 *
12781 * --------------------------------------------------------------*/
12782NK_INTERN float
12783nk_font_text_width(nk_handle handle, float height, const char *text, int len)
12784{
12785 nk_rune unicode;
12786 int text_len = 0;
12787 float text_width = 0;
12788 int glyph_len = 0;
12789 float scale = 0;
12790
12791 struct nk_font *font = (struct nk_font*)handle.ptr;
12792 NK_ASSERT(font);
12793 NK_ASSERT(font->glyphs);
12794 if (!font || !text || !len)
12795 return 0;
12796
12797 scale = height/font->info.height;
12798 glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
12799 if (!glyph_len) return 0;
12800 while (text_len <= (int)len && glyph_len) {
12801 const struct nk_font_glyph *g;
12802 if (unicode == NK_UTF_INVALID) break;
12803
12804 /* query currently drawn glyph information */
12805 g = nk_font_find_glyph(font, unicode);
12806 text_width += g->xadvance * scale;
12807
12808 /* offset next glyph */
12809 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
12810 text_len += glyph_len;
12811 }
12812 return text_width;
12813}
12814#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
12815NK_INTERN void
12816nk_font_query_font_glyph(nk_handle handle, float height,
12817 struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
12818{
12819 float scale;
12820 const struct nk_font_glyph *g;
12821 struct nk_font *font;
12822
12823 NK_ASSERT(glyph);
12824 NK_UNUSED(next_codepoint);
12825
12826 font = (struct nk_font*)handle.ptr;
12827 NK_ASSERT(font);
12828 NK_ASSERT(font->glyphs);
12829 if (!font || !glyph)
12830 return;
12831
12832 scale = height/font->info.height;
12833 g = nk_font_find_glyph(font, codepoint);
12834 glyph->width = (g->x1 - g->x0) * scale;
12835 glyph->height = (g->y1 - g->y0) * scale;
12836 glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
12837 glyph->xadvance = (g->xadvance * scale);
12838 glyph->uv[0] = nk_vec2(g->u0, g->v0);
12839 glyph->uv[1] = nk_vec2(g->u1, g->v1);
12840}
12841#endif
12842NK_API const struct nk_font_glyph*
12843nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
12844{
12845 int i = 0;
12846 int count;
12847 int total_glyphs = 0;
12848 const struct nk_font_glyph *glyph = 0;
12849 const struct nk_font_config *iter = 0;
12850
12851 NK_ASSERT(font);
12852 NK_ASSERT(font->glyphs);
12853 NK_ASSERT(font->info.ranges);
12854 if (!font || !font->glyphs) return 0;
12855
12856 glyph = font->fallback;
12857 iter = font->config;
12858 do {count = nk_range_count(iter->range);
12859 for (i = 0; i < count; ++i) {
12860 nk_rune f = iter->range[(i*2)+0];
12861 nk_rune t = iter->range[(i*2)+1];
12862 int diff = (int)((t - f) + 1);
12863 if (unicode >= f && unicode <= t)
12864 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
12865 total_glyphs += diff;
12866 }
12867 } while ((iter = iter->n) != font->config);
12868 return glyph;
12869}
12870NK_INTERN void
12871nk_font_init(struct nk_font *font, float pixel_height,
12872 nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
12873 const struct nk_baked_font *baked_font, nk_handle atlas)
12874{
12875 struct nk_baked_font baked;
12876 NK_ASSERT(font);
12877 NK_ASSERT(glyphs);
12878 NK_ASSERT(baked_font);
12879 if (!font || !glyphs || !baked_font)
12880 return;
12881
12882 baked = *baked_font;
12883 font->fallback = 0;
12884 font->info = baked;
12885 font->scale = (float)pixel_height / (float)font->info.height;
12886 font->glyphs = &glyphs[baked_font->glyph_offset];
12887 font->texture = atlas;
12888 font->fallback_codepoint = fallback_codepoint;
12889 font->fallback = nk_font_find_glyph(font, fallback_codepoint);
12890
12891 font->handle.height = font->info.height * font->scale;
12892 font->handle.width = nk_font_text_width;
12893 font->handle.userdata.ptr = font;
12894#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
12895 font->handle.query = nk_font_query_font_glyph;
12896 font->handle.texture = font->texture;
12897#endif
12898}
12899
12900/* ---------------------------------------------------------------------------
12901 *
12902 * DEFAULT FONT
12903 *
12904 * ProggyClean.ttf
12905 * Copyright (c) 2004, 2005 Tristan Grimmer
12906 * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
12907 * Download and more information at http://upperbounds.net
12908 *-----------------------------------------------------------------------------*/
12909#ifdef __clang__
12910#pragma clang diagnostic push
12911#pragma clang diagnostic ignored "-Woverlength-strings"
12912#elif defined(__GNUC__) || defined(__GNUG__)
12913#pragma GCC diagnostic push
12914#pragma GCC diagnostic ignored "-Woverlength-strings"
12915#endif
12916
12917#ifdef NK_INCLUDE_DEFAULT_FONT
12918
12919NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
12920 "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
12921 "2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
12922 "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
12923 "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
12924 "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N"
12925 "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)"
12926 "tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX"
12927 "ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
12928 "x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G"
12929 "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)"
12930 "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
12931 "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
12932 "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
12933 "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
12934 "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L"
12935 "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#"
12936 "OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)("
12937 "h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h"
12938 "o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
12939 "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-"
12940 "sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-"
12941 "eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO"
12942 "M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
12943 "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
12944 "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
12945 "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
12946 "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
12947 "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
12948 "nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
12949 "7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
12950 ")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
12951 "D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
12952 "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
12953 "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
12954 "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-"
12955 "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
12956 "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7"
12957 ".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@"
12958 "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
12959 "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
12960 "@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#"
12961 "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#"
12962 "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0"
12963 "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
12964 "6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
12965 "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD"
12966 ":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+"
12967 "tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*"
12968 "$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7"
12969 ":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A"
12970 "7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7"
12971 "u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT"
12972 "LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M"
12973 ":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>"
12974 "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
12975 "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
12976 "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
12977 "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%"
12978 "9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-"
12979 "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
12980 "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY"
12981 "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
12982 "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`"
12983 "0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/"
12984 "+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
12985 "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V"
12986 "?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK"
12987 "Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa"
12988 ">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>"
12989 "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
12990 "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#"
12991 "Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$"
12992 "MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
12993 "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
12994 "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
12995 "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO"
12996 "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
12997 ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>"
12998 "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#"
12999 "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
13000 "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
13001 "/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#"
13002 "m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#"
13003 "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
13004 "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
13005 "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
13006
13007#endif /* NK_INCLUDE_DEFAULT_FONT */
13008
13009#define NK_CURSOR_DATA_W 90
13010#define NK_CURSOR_DATA_H 27
13011NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
13012{
13013 "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX"
13014 "..- -X.....X- X.X - X.X -X.....X - X.....X"
13015 "--- -XXX.XXX- X...X - X...X -X....X - X....X"
13016 "X - X.X - X.....X - X.....X -X...X - X...X"
13017 "XX - X.X -X.......X- X.......X -X..X.X - X.X..X"
13018 "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X"
13019 "X..X - X.X - X.X - X.X -XX X.X - X.X XX"
13020 "X...X - X.X - X.X - XX X.X XX - X.X - X.X "
13021 "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X "
13022 "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X "
13023 "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X "
13024 "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X "
13025 "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X "
13026 "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X "
13027 "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X "
13028 "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X "
13029 "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX "
13030 "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------"
13031 "X.X X..X - -X.......X- X.......X - XX XX - "
13032 "XX X..X - - X.....X - X.....X - X.X X.X - "
13033 " X..X - X...X - X...X - X..X X..X - "
13034 " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - "
13035 "------------ - X - X -X.....................X- "
13036 " ----------------------------------- X...XXXXXXXXXXXXX...X - "
13037 " - X..X X..X - "
13038 " - X.X X.X - "
13039 " - XX XX - "
13040};
13041
13042#ifdef __clang__
13043#pragma clang diagnostic pop
13044#elif defined(__GNUC__) || defined(__GNUG__)
13045#pragma GCC diagnostic pop
13046#endif
13047
13048NK_GLOBAL unsigned char *nk__barrier;
13049NK_GLOBAL unsigned char *nk__barrier2;
13050NK_GLOBAL unsigned char *nk__barrier3;
13051NK_GLOBAL unsigned char *nk__barrier4;
13052NK_GLOBAL unsigned char *nk__dout;
13053
13054NK_INTERN unsigned int
13055nk_decompress_length(unsigned char *input)
13056{
13057 return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
13058}
13059NK_INTERN void
13060nk__match(unsigned char *data, unsigned int length)
13061{
13062 /* INVERSE of memmove... write each byte before copying the next...*/
13063 NK_ASSERT (nk__dout + length <= nk__barrier);
13064 if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
13065 if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
13066 while (length--) *nk__dout++ = *data++;
13067}
13068NK_INTERN void
13069nk__lit(unsigned char *data, unsigned int length)
13070{
13071 NK_ASSERT (nk__dout + length <= nk__barrier);
13072 if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
13073 if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
13074 NK_MEMCPY(nk__dout, data, length);
13075 nk__dout += length;
13076}
13077NK_INTERN unsigned char*
13078nk_decompress_token(unsigned char *i)
13079{
13080 #define nk__in2(x) ((i[x] << 8) + i[(x)+1])
13081 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1))
13082 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1))
13083
13084 if (*i >= 0x20) { /* use fewer if's for cases that expand small */
13085 if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
13086 else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
13087 else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
13088 } else { /* more ifs for cases that expand large, since overhead is amortized */
13089 if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
13090 else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
13091 else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
13092 else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
13093 else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
13094 else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
13095 }
13096 return i;
13097}
13098NK_INTERN unsigned int
13099nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
13100{
13101 const unsigned long ADLER_MOD = 65521;
13102 unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
13103 unsigned long blocklen, i;
13104
13105 blocklen = buflen % 5552;
13106 while (buflen) {
13107 for (i=0; i + 7 < blocklen; i += 8) {
13108 s1 += buffer[0]; s2 += s1;
13109 s1 += buffer[1]; s2 += s1;
13110 s1 += buffer[2]; s2 += s1;
13111 s1 += buffer[3]; s2 += s1;
13112 s1 += buffer[4]; s2 += s1;
13113 s1 += buffer[5]; s2 += s1;
13114 s1 += buffer[6]; s2 += s1;
13115 s1 += buffer[7]; s2 += s1;
13116 buffer += 8;
13117 }
13118 for (; i < blocklen; ++i) {
13119 s1 += *buffer++; s2 += s1;
13120 }
13121
13122 s1 %= ADLER_MOD; s2 %= ADLER_MOD;
13123 buflen -= (unsigned int)blocklen;
13124 blocklen = 5552;
13125 }
13126 return (unsigned int)(s2 << 16) + (unsigned int)s1;
13127}
13128NK_INTERN unsigned int
13129nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
13130{
13131 unsigned int olen;
13132 if (nk__in4(0) != 0x57bC0000) return 0;
13133 if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */
13134 olen = nk_decompress_length(i);
13135 nk__barrier2 = i;
13136 nk__barrier3 = i+length;
13137 nk__barrier = output + olen;
13138 nk__barrier4 = output;
13139 i += 16;
13140
13141 nk__dout = output;
13142 for (;;) {
13143 unsigned char *old_i = i;
13144 i = nk_decompress_token(i);
13145 if (i == old_i) {
13146 if (*i == 0x05 && i[1] == 0xfa) {
13147 NK_ASSERT(nk__dout == output + olen);
13148 if (nk__dout != output + olen) return 0;
13149 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
13150 return 0;
13151 return olen;
13152 } else {
13153 NK_ASSERT(0); /* NOTREACHED */
13154 return 0;
13155 }
13156 }
13157 NK_ASSERT(nk__dout <= output + olen);
13158 if (nk__dout > output + olen)
13159 return 0;
13160 }
13161}
13162NK_INTERN unsigned int
13163nk_decode_85_byte(char c)
13164{
13165 return (unsigned int)((c >= '\\') ? c-36 : c-35);
13166}
13167NK_INTERN void
13168nk_decode_85(unsigned char* dst, const unsigned char* src)
13169{
13170 while (*src)
13171 {
13172 unsigned int tmp =
13173 nk_decode_85_byte((char)src[0]) +
13174 85 * (nk_decode_85_byte((char)src[1]) +
13175 85 * (nk_decode_85_byte((char)src[2]) +
13176 85 * (nk_decode_85_byte((char)src[3]) +
13177 85 * nk_decode_85_byte((char)src[4]))));
13178
13179 /* we can't assume little-endianess. */
13180 dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
13181 dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
13182 dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
13183 dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
13184
13185 src += 5;
13186 dst += 4;
13187 }
13188}
13189
13190/* -------------------------------------------------------------
13191 *
13192 * FONT ATLAS
13193 *
13194 * --------------------------------------------------------------*/
13195NK_API struct nk_font_config
13196nk_font_config(float pixel_height)
13197{
13198 struct nk_font_config cfg;
13199 nk_zero_struct(cfg);
13200 cfg.ttf_blob = 0;
13201 cfg.ttf_size = 0;
13202 cfg.ttf_data_owned_by_atlas = 0;
13203 cfg.size = pixel_height;
13204 cfg.oversample_h = 3;
13205 cfg.oversample_v = 1;
13206 cfg.pixel_snap = 0;
13207 cfg.coord_type = NK_COORD_UV;
13208 cfg.spacing = nk_vec2(0,0);
13209 cfg.range = nk_font_default_glyph_ranges();
13210 cfg.merge_mode = 0;
13211 cfg.fallback_glyph = '?';
13212 cfg.font = 0;
13213 cfg.n = 0;
13214 return cfg;
13215}
13216#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
13217NK_API void
13218nk_font_atlas_init_default(struct nk_font_atlas *atlas)
13219{
13220 NK_ASSERT(atlas);
13221 if (!atlas) return;
13222 nk_zero_struct(*atlas);
13223 atlas->temporary.userdata.ptr = 0;
13224 atlas->temporary.alloc = nk_malloc;
13225 atlas->temporary.free = nk_mfree;
13226 atlas->permanent.userdata.ptr = 0;
13227 atlas->permanent.alloc = nk_malloc;
13228 atlas->permanent.free = nk_mfree;
13229}
13230#endif
13231NK_API void
13232nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
13233{
13234 NK_ASSERT(atlas);
13235 NK_ASSERT(alloc);
13236 if (!atlas || !alloc) return;
13237 nk_zero_struct(*atlas);
13238 atlas->permanent = *alloc;
13239 atlas->temporary = *alloc;
13240}
13241NK_API void
13242nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
13243 struct nk_allocator *permanent, struct nk_allocator *temporary)
13244{
13245 NK_ASSERT(atlas);
13246 NK_ASSERT(permanent);
13247 NK_ASSERT(temporary);
13248 if (!atlas || !permanent || !temporary) return;
13249 nk_zero_struct(*atlas);
13250 atlas->permanent = *permanent;
13251 atlas->temporary = *temporary;
13252}
13253NK_API void
13254nk_font_atlas_begin(struct nk_font_atlas *atlas)
13255{
13256 NK_ASSERT(atlas);
13257 NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
13258 NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
13259 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
13260 !atlas->temporary.alloc || !atlas->temporary.free) return;
13261 if (atlas->glyphs) {
13262 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13263 atlas->glyphs = 0;
13264 }
13265 if (atlas->pixel) {
13266 atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
13267 atlas->pixel = 0;
13268 }
13269}
13270NK_API struct nk_font*
13271nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
13272{
13273 struct nk_font *font = 0;
13274 struct nk_font_config *cfg;
13275
13276 NK_ASSERT(atlas);
13277 NK_ASSERT(atlas->permanent.alloc);
13278 NK_ASSERT(atlas->permanent.free);
13279 NK_ASSERT(atlas->temporary.alloc);
13280 NK_ASSERT(atlas->temporary.free);
13281
13282 NK_ASSERT(config);
13283 NK_ASSERT(config->ttf_blob);
13284 NK_ASSERT(config->ttf_size);
13285 NK_ASSERT(config->size > 0.0f);
13286
13287 if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
13288 !atlas->permanent.alloc || !atlas->permanent.free ||
13289 !atlas->temporary.alloc || !atlas->temporary.free)
13290 return 0;
13291
13292 /* allocate font config */
13293 cfg = (struct nk_font_config*)
13294 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
13295 NK_MEMCPY(cfg, config, sizeof(*config));
13296 cfg->n = cfg;
13297 cfg->p = cfg;
13298
13299 if (!config->merge_mode) {
13300 /* insert font config into list */
13301 if (!atlas->config) {
13302 atlas->config = cfg;
13303 cfg->next = 0;
13304 } else {
13305 struct nk_font_config *i = atlas->config;
13306 while (i->next) i = i->next;
13307 i->next = cfg;
13308 cfg->next = 0;
13309 }
13310 /* allocate new font */
13311 font = (struct nk_font*)
13312 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
13313 NK_ASSERT(font);
13314 nk_zero(font, sizeof(*font));
13315 if (!font) return 0;
13316 font->config = cfg;
13317
13318 /* insert font into list */
13319 if (!atlas->fonts) {
13320 atlas->fonts = font;
13321 font->next = 0;
13322 } else {
13323 struct nk_font *i = atlas->fonts;
13324 while (i->next) i = i->next;
13325 i->next = font;
13326 font->next = 0;
13327 }
13328 cfg->font = &font->info;
13329 } else {
13330 /* extend previously added font */
13331 struct nk_font *f = 0;
13332 struct nk_font_config *c = 0;
13333 NK_ASSERT(atlas->font_num);
13334 f = atlas->fonts;
13335 c = f->config;
13336 cfg->font = &f->info;
13337
13338 cfg->n = c;
13339 cfg->p = c->p;
13340 c->p->n = cfg;
13341 c->p = cfg;
13342 }
13343 /* create own copy of .TTF font blob */
13344 if (!config->ttf_data_owned_by_atlas) {
13345 cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
13346 NK_ASSERT(cfg->ttf_blob);
13347 if (!cfg->ttf_blob) {
13348 atlas->font_num++;
13349 return 0;
13350 }
13351 NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
13352 cfg->ttf_data_owned_by_atlas = 1;
13353 }
13354 atlas->font_num++;
13355 return font;
13356}
13357NK_API struct nk_font*
13358nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
13359 nk_size size, float height, const struct nk_font_config *config)
13360{
13361 struct nk_font_config cfg;
13362 NK_ASSERT(memory);
13363 NK_ASSERT(size);
13364
13365 NK_ASSERT(atlas);
13366 NK_ASSERT(atlas->temporary.alloc);
13367 NK_ASSERT(atlas->temporary.free);
13368 NK_ASSERT(atlas->permanent.alloc);
13369 NK_ASSERT(atlas->permanent.free);
13370 if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
13371 !atlas->permanent.alloc || !atlas->permanent.free)
13372 return 0;
13373
13374 cfg = (config) ? *config: nk_font_config(height);
13375 cfg.ttf_blob = memory;
13376 cfg.ttf_size = size;
13377 cfg.size = height;
13378 cfg.ttf_data_owned_by_atlas = 0;
13379 return nk_font_atlas_add(atlas, &cfg);
13380}
13381#ifdef NK_INCLUDE_STANDARD_IO
13382NK_API struct nk_font*
13383nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
13384 float height, const struct nk_font_config *config)
13385{
13386 nk_size size;
13387 char *memory;
13388 struct nk_font_config cfg;
13389
13390 NK_ASSERT(atlas);
13391 NK_ASSERT(atlas->temporary.alloc);
13392 NK_ASSERT(atlas->temporary.free);
13393 NK_ASSERT(atlas->permanent.alloc);
13394 NK_ASSERT(atlas->permanent.free);
13395
13396 if (!atlas || !file_path) return 0;
13397 memory = nk_file_load(file_path, &size, &atlas->permanent);
13398 if (!memory) return 0;
13399
13400 cfg = (config) ? *config: nk_font_config(height);
13401 cfg.ttf_blob = memory;
13402 cfg.ttf_size = size;
13403 cfg.size = height;
13404 cfg.ttf_data_owned_by_atlas = 1;
13405 return nk_font_atlas_add(atlas, &cfg);
13406}
13407#endif
13408NK_API struct nk_font*
13409nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
13410 void *compressed_data, nk_size compressed_size, float height,
13411 const struct nk_font_config *config)
13412{
13413 unsigned int decompressed_size;
13414 void *decompressed_data;
13415 struct nk_font_config cfg;
13416
13417 NK_ASSERT(atlas);
13418 NK_ASSERT(atlas->temporary.alloc);
13419 NK_ASSERT(atlas->temporary.free);
13420 NK_ASSERT(atlas->permanent.alloc);
13421 NK_ASSERT(atlas->permanent.free);
13422
13423 NK_ASSERT(compressed_data);
13424 NK_ASSERT(compressed_size);
13425 if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
13426 !atlas->permanent.alloc || !atlas->permanent.free)
13427 return 0;
13428
13429 decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
13430 decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
13431 NK_ASSERT(decompressed_data);
13432 if (!decompressed_data) return 0;
13433 nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
13434 (unsigned int)compressed_size);
13435
13436 cfg = (config) ? *config: nk_font_config(height);
13437 cfg.ttf_blob = decompressed_data;
13438 cfg.ttf_size = decompressed_size;
13439 cfg.size = height;
13440 cfg.ttf_data_owned_by_atlas = 1;
13441 return nk_font_atlas_add(atlas, &cfg);
13442}
13443NK_API struct nk_font*
13444nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
13445 const char *data_base85, float height, const struct nk_font_config *config)
13446{
13447 int compressed_size;
13448 void *compressed_data;
13449 struct nk_font *font;
13450
13451 NK_ASSERT(atlas);
13452 NK_ASSERT(atlas->temporary.alloc);
13453 NK_ASSERT(atlas->temporary.free);
13454 NK_ASSERT(atlas->permanent.alloc);
13455 NK_ASSERT(atlas->permanent.free);
13456
13457 NK_ASSERT(data_base85);
13458 if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
13459 !atlas->permanent.alloc || !atlas->permanent.free)
13460 return 0;
13461
13462 compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
13463 compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
13464 NK_ASSERT(compressed_data);
13465 if (!compressed_data) return 0;
13466 nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
13467 font = nk_font_atlas_add_compressed(atlas, compressed_data,
13468 (nk_size)compressed_size, height, config);
13469 atlas->temporary.free(atlas->temporary.userdata, compressed_data);
13470 return font;
13471}
13472
13473#ifdef NK_INCLUDE_DEFAULT_FONT
13474NK_API struct nk_font*
13475nk_font_atlas_add_default(struct nk_font_atlas *atlas,
13476 float pixel_height, const struct nk_font_config *config)
13477{
13478 NK_ASSERT(atlas);
13479 NK_ASSERT(atlas->temporary.alloc);
13480 NK_ASSERT(atlas->temporary.free);
13481 NK_ASSERT(atlas->permanent.alloc);
13482 NK_ASSERT(atlas->permanent.free);
13483 return nk_font_atlas_add_compressed_base85(atlas,
13484 nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
13485}
13486#endif
13487NK_API const void*
13488nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
13489 enum nk_font_atlas_format fmt)
13490{
13491 int i = 0;
13492 void *tmp = 0;
13493 nk_size tmp_size, img_size;
13494 struct nk_font *font_iter;
13495 struct nk_font_baker *baker;
13496
13497 NK_ASSERT(atlas);
13498 NK_ASSERT(atlas->temporary.alloc);
13499 NK_ASSERT(atlas->temporary.free);
13500 NK_ASSERT(atlas->permanent.alloc);
13501 NK_ASSERT(atlas->permanent.free);
13502
13503 NK_ASSERT(width);
13504 NK_ASSERT(height);
13505 if (!atlas || !width || !height ||
13506 !atlas->temporary.alloc || !atlas->temporary.free ||
13507 !atlas->permanent.alloc || !atlas->permanent.free)
13508 return 0;
13509
13510#ifdef NK_INCLUDE_DEFAULT_FONT
13511 /* no font added so just use default font */
13512 if (!atlas->font_num)
13513 atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
13514#endif
13515 NK_ASSERT(atlas->font_num);
13516 if (!atlas->font_num) return 0;
13517
13518 /* allocate temporary baker memory required for the baking process */
13519 nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
13520 tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
13521 NK_ASSERT(tmp);
13522 if (!tmp) goto failed;
13523
13524 /* allocate glyph memory for all fonts */
13525 baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
13526 atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
13527 atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
13528 NK_ASSERT(atlas->glyphs);
13529 if (!atlas->glyphs)
13530 goto failed;
13531
13532 /* pack all glyphs into a tight fit space */
13533 atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
13534 atlas->custom.h = NK_CURSOR_DATA_H + 1;
13535 if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
13536 atlas->config, atlas->font_num, &atlas->temporary))
13537 goto failed;
13538
13539 /* allocate memory for the baked image font atlas */
13540 atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
13541 NK_ASSERT(atlas->pixel);
13542 if (!atlas->pixel)
13543 goto failed;
13544
13545 /* bake glyphs and custom white pixel into image */
13546 nk_font_bake(baker, atlas->pixel, *width, *height,
13547 atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
13548 nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
13549 nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
13550
13551 if (fmt == NK_FONT_ATLAS_RGBA32) {
13552 /* convert alpha8 image into rgba32 image */
13553 void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
13554 (nk_size)(*width * *height * 4));
13555 NK_ASSERT(img_rgba);
13556 if (!img_rgba) goto failed;
13557 nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
13558 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13559 atlas->pixel = img_rgba;
13560 }
13561 atlas->tex_width = *width;
13562 atlas->tex_height = *height;
13563
13564 /* initialize each font */
13565 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
13566 struct nk_font *font = font_iter;
13567 struct nk_font_config *config = font->config;
13568 nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
13569 config->font, nk_handle_ptr(0));
13570 }
13571
13572 /* initialize each cursor */
13573 {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
13574 /* Pos Size Offset */
13575 {{ 0, 3}, {12,19}, { 0, 0}},
13576 {{13, 0}, { 7,16}, { 4, 8}},
13577 {{31, 0}, {23,23}, {11,11}},
13578 {{21, 0}, { 9, 23}, { 5,11}},
13579 {{55,18}, {23, 9}, {11, 5}},
13580 {{73, 0}, {17,17}, { 9, 9}},
13581 {{55, 0}, {17,17}, { 9, 9}}
13582 };
13583 for (i = 0; i < NK_CURSOR_COUNT; ++i) {
13584 struct nk_cursor *cursor = &atlas->cursors[i];
13585 cursor->img.w = (unsigned short)*width;
13586 cursor->img.h = (unsigned short)*height;
13587 cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
13588 cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
13589 cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
13590 cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
13591 cursor->size = nk_cursor_data[i][1];
13592 cursor->offset = nk_cursor_data[i][2];
13593 }}
13594 /* free temporary memory */
13595 atlas->temporary.free(atlas->temporary.userdata, tmp);
13596 return atlas->pixel;
13597
13598failed:
13599 /* error so cleanup all memory */
13600 if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
13601 if (atlas->glyphs) {
13602 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13603 atlas->glyphs = 0;
13604 }
13605 if (atlas->pixel) {
13606 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13607 atlas->pixel = 0;
13608 }
13609 return 0;
13610}
13611NK_API void
13612nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
13613 struct nk_draw_null_texture *null)
13614{
13615 int i = 0;
13616 struct nk_font *font_iter;
13617 NK_ASSERT(atlas);
13618 if (!atlas) {
13619 if (!null) return;
13620 null->texture = texture;
13621 null->uv = nk_vec2(0.5f,0.5f);
13622 }
13623 if (null) {
13624 null->texture = texture;
13625 null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
13626 null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
13627 }
13628 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
13629 font_iter->texture = texture;
13630#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
13631 font_iter->handle.texture = texture;
13632#endif
13633 }
13634 for (i = 0; i < NK_CURSOR_COUNT; ++i)
13635 atlas->cursors[i].img.handle = texture;
13636
13637 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13638 atlas->pixel = 0;
13639 atlas->tex_width = 0;
13640 atlas->tex_height = 0;
13641 atlas->custom.x = 0;
13642 atlas->custom.y = 0;
13643 atlas->custom.w = 0;
13644 atlas->custom.h = 0;
13645}
13646NK_API void
13647nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
13648{
13649 NK_ASSERT(atlas);
13650 NK_ASSERT(atlas->temporary.alloc);
13651 NK_ASSERT(atlas->temporary.free);
13652 NK_ASSERT(atlas->permanent.alloc);
13653 NK_ASSERT(atlas->permanent.free);
13654 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
13655 if (atlas->config) {
13656 struct nk_font_config *iter;
13657 for (iter = atlas->config; iter; iter = iter->next) {
13658 struct nk_font_config *i;
13659 for (i = iter->n; i != iter; i = i->n) {
13660 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
13661 i->ttf_blob = 0;
13662 }
13663 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
13664 iter->ttf_blob = 0;
13665 }
13666 }
13667}
13668NK_API void
13669nk_font_atlas_clear(struct nk_font_atlas *atlas)
13670{
13671 NK_ASSERT(atlas);
13672 NK_ASSERT(atlas->temporary.alloc);
13673 NK_ASSERT(atlas->temporary.free);
13674 NK_ASSERT(atlas->permanent.alloc);
13675 NK_ASSERT(atlas->permanent.free);
13676 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
13677
13678 if (atlas->config) {
13679 struct nk_font_config *iter, *next;
13680 for (iter = atlas->config; iter; iter = next) {
13681 struct nk_font_config *i, *n;
13682 for (i = iter->n; i != iter; i = n) {
13683 n = i->n;
13684 if (i->ttf_blob)
13685 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
13686 atlas->permanent.free(atlas->permanent.userdata, i);
13687 }
13688 next = iter->next;
13689 if (i->ttf_blob)
13690 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
13691 atlas->permanent.free(atlas->permanent.userdata, iter);
13692 }
13693 atlas->config = 0;
13694 }
13695 if (atlas->fonts) {
13696 struct nk_font *iter, *next;
13697 for (iter = atlas->fonts; iter; iter = next) {
13698 next = iter->next;
13699 atlas->permanent.free(atlas->permanent.userdata, iter);
13700 }
13701 atlas->fonts = 0;
13702 }
13703 if (atlas->glyphs)
13704 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13705 nk_zero_struct(*atlas);
13706}
13707#endif
13708
13709
13710
13711
13712/* ===============================================================
13713 *
13714 * INPUT
13715 *
13716 * ===============================================================*/
13717NK_API void
13718nk_input_begin(struct nk_context *ctx)
13719{
13720 int i;
13721 struct nk_input *in;
13722 NK_ASSERT(ctx);
13723 if (!ctx) return;
13724 in = &ctx->input;
13725 for (i = 0; i < NK_BUTTON_MAX; ++i)
13726 in->mouse.buttons[i].clicked = 0;
13727
13728 in->keyboard.text_len = 0;
13729 in->mouse.scroll_delta = nk_vec2(0,0);
13730 in->mouse.prev.x = in->mouse.pos.x;
13731 in->mouse.prev.y = in->mouse.pos.y;
13732 in->mouse.delta.x = 0;
13733 in->mouse.delta.y = 0;
13734 for (i = 0; i < NK_KEY_MAX; i++)
13735 in->keyboard.keys[i].clicked = 0;
13736}
13737NK_API void
13738nk_input_end(struct nk_context *ctx)
13739{
13740 struct nk_input *in;
13741 NK_ASSERT(ctx);
13742 if (!ctx) return;
13743 in = &ctx->input;
13744 if (in->mouse.grab)
13745 in->mouse.grab = 0;
13746 if (in->mouse.ungrab) {
13747 in->mouse.grabbed = 0;
13748 in->mouse.ungrab = 0;
13749 in->mouse.grab = 0;
13750 }
13751}
13752NK_API void
13753nk_input_motion(struct nk_context *ctx, int x, int y)
13754{
13755 struct nk_input *in;
13756 NK_ASSERT(ctx);
13757 if (!ctx) return;
13758 in = &ctx->input;
13759 in->mouse.pos.x = (float)x;
13760 in->mouse.pos.y = (float)y;
13761 in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
13762 in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
13763}
13764NK_API void
13765nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
13766{
13767 struct nk_input *in;
13768 NK_ASSERT(ctx);
13769 if (!ctx) return;
13770 in = &ctx->input;
13771#ifdef NK_KEYSTATE_BASED_INPUT
13772 if (in->keyboard.keys[key].down != down)
13773 in->keyboard.keys[key].clicked++;
13774#else
13775 in->keyboard.keys[key].clicked++;
13776#endif
13777 in->keyboard.keys[key].down = down;
13778}
13779NK_API void
13780nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
13781{
13782 struct nk_mouse_button *btn;
13783 struct nk_input *in;
13784 NK_ASSERT(ctx);
13785 if (!ctx) return;
13786 in = &ctx->input;
13787 if (in->mouse.buttons[id].down == down) return;
13788
13789 btn = &in->mouse.buttons[id];
13790 btn->clicked_pos.x = (float)x;
13791 btn->clicked_pos.y = (float)y;
13792 btn->down = down;
13793 btn->clicked++;
13794}
13795NK_API void
13796nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
13797{
13798 NK_ASSERT(ctx);
13799 if (!ctx) return;
13800 ctx->input.mouse.scroll_delta.x += val.x;
13801 ctx->input.mouse.scroll_delta.y += val.y;
13802}
13803NK_API void
13804nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
13805{
13806 int len = 0;
13807 nk_rune unicode;
13808 struct nk_input *in;
13809
13810 NK_ASSERT(ctx);
13811 if (!ctx) return;
13812 in = &ctx->input;
13813
13814 len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
13815 if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
13816 nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
13818 in->keyboard.text_len += len;
13819 }
13820}
13821NK_API void
13822nk_input_char(struct nk_context *ctx, char c)
13823{
13824 nk_glyph glyph;
13825 NK_ASSERT(ctx);
13826 if (!ctx) return;
13827 glyph[0] = c;
13828 nk_input_glyph(ctx, glyph);
13829}
13830NK_API void
13831nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
13832{
13833 nk_glyph rune;
13834 NK_ASSERT(ctx);
13835 if (!ctx) return;
13836 nk_utf_encode(unicode, rune, NK_UTF_SIZE);
13837 nk_input_glyph(ctx, rune);
13838}
13839NK_API int
13840nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
13841{
13842 const struct nk_mouse_button *btn;
13843 if (!i) return nk_false;
13844 btn = &i->mouse.buttons[id];
13845 return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
13846}
13847NK_API int
13849 struct nk_rect b)
13850{
13851 const struct nk_mouse_button *btn;
13852 if (!i) return nk_false;
13853 btn = &i->mouse.buttons[id];
13854 if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
13855 return nk_false;
13856 return nk_true;
13857}
13858NK_API int
13860 struct nk_rect b, int down)
13861{
13862 const struct nk_mouse_button *btn;
13863 if (!i) return nk_false;
13864 btn = &i->mouse.buttons[id];
13865 return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
13866}
13867NK_API int
13868nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
13869 struct nk_rect b)
13870{
13871 const struct nk_mouse_button *btn;
13872 if (!i) return nk_false;
13873 btn = &i->mouse.buttons[id];
13875 btn->clicked) ? nk_true : nk_false;
13876}
13877NK_API int
13879 struct nk_rect b, int down)
13880{
13881 const struct nk_mouse_button *btn;
13882 if (!i) return nk_false;
13883 btn = &i->mouse.buttons[id];
13884 return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
13885 btn->clicked) ? nk_true : nk_false;
13886}
13887NK_API int
13888nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
13889{
13890 int i, down = 0;
13891 for (i = 0; i < NK_BUTTON_MAX; ++i)
13893 return down;
13894}
13895NK_API int
13896nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
13897{
13898 if (!i) return nk_false;
13899 return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
13900}
13901NK_API int
13902nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
13903{
13904 if (!i) return nk_false;
13905 return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
13906}
13907NK_API int
13908nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
13909{
13910 if (!i) return nk_false;
13911 if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
13912 return nk_input_is_mouse_click_in_rect(i, id, rect);
13913}
13914NK_API int
13915nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
13916{
13917 if (!i) return nk_false;
13918 return i->mouse.buttons[id].down;
13919}
13920NK_API int
13921nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
13922{
13923 const struct nk_mouse_button *b;
13924 if (!i) return nk_false;
13925 b = &i->mouse.buttons[id];
13926 if (b->down && b->clicked)
13927 return nk_true;
13928 return nk_false;
13929}
13930NK_API int
13931nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
13932{
13933 if (!i) return nk_false;
13934 return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
13935}
13936NK_API int
13937nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
13938{
13939 const struct nk_key *k;
13940 if (!i) return nk_false;
13941 k = &i->keyboard.keys[key];
13942 if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
13943 return nk_true;
13944 return nk_false;
13945}
13946NK_API int
13947nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
13948{
13949 const struct nk_key *k;
13950 if (!i) return nk_false;
13951 k = &i->keyboard.keys[key];
13952 if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
13953 return nk_true;
13954 return nk_false;
13955}
13956NK_API int
13957nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
13958{
13959 const struct nk_key *k;
13960 if (!i) return nk_false;
13961 k = &i->keyboard.keys[key];
13962 if (k->down) return nk_true;
13963 return nk_false;
13964}
13965
13966
13967
13968
13969/* ===============================================================
13970 *
13971 * STYLE
13972 *
13973 * ===============================================================*/
13974NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
13975#define NK_COLOR_MAP(NK_COLOR)\
13976 NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \
13977 NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \
13978 NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \
13979 NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \
13980 NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \
13981 NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \
13982 NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \
13983 NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \
13984 NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \
13985 NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \
13986 NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \
13987 NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \
13988 NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \
13989 NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \
13990 NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \
13991 NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
13992 NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \
13993 NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \
13994 NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \
13995 NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \
13996 NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \
13997 NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \
13998 NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT, 255, 0, 0, 255) \
13999 NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \
14000 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \
14001 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \
14002 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \
14003 NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255)
14004
14005NK_GLOBAL const struct nk_color
14006nk_default_color_style[NK_COLOR_COUNT] = {
14007#define NK_COLOR(a,b,c,d,e) {b,c,d,e},
14008 NK_COLOR_MAP(NK_COLOR)
14009#undef NK_COLOR
14010};
14011NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
14012#define NK_COLOR(a,b,c,d,e) #a,
14013 NK_COLOR_MAP(NK_COLOR)
14014#undef NK_COLOR
14015};
14016
14017NK_API const char*
14019{
14020 return nk_color_names[c];
14021}
14022NK_API struct nk_style_item
14023nk_style_item_image(struct nk_image img)
14024{
14025 struct nk_style_item i;
14026 i.type = NK_STYLE_ITEM_IMAGE;
14027 i.data.image = img;
14028 return i;
14029}
14030NK_API struct nk_style_item
14031nk_style_item_color(struct nk_color col)
14032{
14033 struct nk_style_item i;
14034 i.type = NK_STYLE_ITEM_COLOR;
14035 i.data.color = col;
14036 return i;
14037}
14038NK_API struct nk_style_item
14040{
14041 struct nk_style_item i;
14042 i.type = NK_STYLE_ITEM_COLOR;
14043 i.data.color = nk_rgba(0,0,0,0);
14044 return i;
14045}
14046NK_API void
14047nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
14048{
14049 struct nk_style *style;
14050 struct nk_style_text *text;
14051 struct nk_style_button *button;
14052 struct nk_style_toggle *toggle;
14053 struct nk_style_selectable *select;
14054 struct nk_style_slider *slider;
14055 struct nk_style_progress *prog;
14056 struct nk_style_scrollbar *scroll;
14057 struct nk_style_edit *edit;
14058 struct nk_style_property *property;
14059 struct nk_style_combo *combo;
14060 struct nk_style_chart *chart;
14061 struct nk_style_tab *tab;
14062 struct nk_style_window *win;
14063
14064 NK_ASSERT(ctx);
14065 if (!ctx) return;
14066 style = &ctx->style;
14067 table = (!table) ? nk_default_color_style: table;
14068
14069 /* default text */
14070 text = &style->text;
14071 text->color = table[NK_COLOR_TEXT];
14072 text->padding = nk_vec2(0,0);
14073
14074 /* default button */
14075 button = &style->button;
14076 nk_zero_struct(*button);
14077 button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]);
14080 button->border_color = table[NK_COLOR_BORDER];
14081 button->text_background = table[NK_COLOR_BUTTON];
14082 button->text_normal = table[NK_COLOR_TEXT];
14083 button->text_hover = table[NK_COLOR_TEXT];
14084 button->text_active = table[NK_COLOR_TEXT];
14085 button->padding = nk_vec2(2.0f,2.0f);
14086 button->image_padding = nk_vec2(0.0f,0.0f);
14087 button->touch_padding = nk_vec2(0.0f, 0.0f);
14088 button->userdata = nk_handle_ptr(0);
14090 button->border = 1.0f;
14091 button->rounding = 4.0f;
14092 button->draw_begin = 0;
14093 button->draw_end = 0;
14094
14095 /* contextual button */
14096 button = &style->contextual_button;
14097 nk_zero_struct(*button);
14098 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
14101 button->border_color = table[NK_COLOR_WINDOW];
14102 button->text_background = table[NK_COLOR_WINDOW];
14103 button->text_normal = table[NK_COLOR_TEXT];
14104 button->text_hover = table[NK_COLOR_TEXT];
14105 button->text_active = table[NK_COLOR_TEXT];
14106 button->padding = nk_vec2(2.0f,2.0f);
14107 button->touch_padding = nk_vec2(0.0f,0.0f);
14108 button->userdata = nk_handle_ptr(0);
14110 button->border = 0.0f;
14111 button->rounding = 0.0f;
14112 button->draw_begin = 0;
14113 button->draw_end = 0;
14114
14115 /* menu button */
14116 button = &style->menu_button;
14117 nk_zero_struct(*button);
14118 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
14119 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
14120 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
14121 button->border_color = table[NK_COLOR_WINDOW];
14122 button->text_background = table[NK_COLOR_WINDOW];
14123 button->text_normal = table[NK_COLOR_TEXT];
14124 button->text_hover = table[NK_COLOR_TEXT];
14125 button->text_active = table[NK_COLOR_TEXT];
14126 button->padding = nk_vec2(2.0f,2.0f);
14127 button->touch_padding = nk_vec2(0.0f,0.0f);
14128 button->userdata = nk_handle_ptr(0);
14130 button->border = 0.0f;
14131 button->rounding = 1.0f;
14132 button->draw_begin = 0;
14133 button->draw_end = 0;
14134
14135 /* checkbox toggle */
14136 toggle = &style->checkbox;
14137 nk_zero_struct(*toggle);
14138 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
14143 toggle->userdata = nk_handle_ptr(0);
14144 toggle->text_background = table[NK_COLOR_WINDOW];
14145 toggle->text_normal = table[NK_COLOR_TEXT];
14146 toggle->text_hover = table[NK_COLOR_TEXT];
14147 toggle->text_active = table[NK_COLOR_TEXT];
14148 toggle->padding = nk_vec2(2.0f, 2.0f);
14149 toggle->touch_padding = nk_vec2(0,0);
14150 toggle->border_color = nk_rgba(0,0,0,0);
14151 toggle->border = 0.0f;
14152 toggle->spacing = 4;
14153
14154 /* option toggle */
14155 toggle = &style->option;
14156 nk_zero_struct(*toggle);
14157 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
14162 toggle->userdata = nk_handle_ptr(0);
14163 toggle->text_background = table[NK_COLOR_WINDOW];
14164 toggle->text_normal = table[NK_COLOR_TEXT];
14165 toggle->text_hover = table[NK_COLOR_TEXT];
14166 toggle->text_active = table[NK_COLOR_TEXT];
14167 toggle->padding = nk_vec2(3.0f, 3.0f);
14168 toggle->touch_padding = nk_vec2(0,0);
14169 toggle->border_color = nk_rgba(0,0,0,0);
14170 toggle->border = 0.0f;
14171 toggle->spacing = 4;
14172
14173 /* selectable */
14174 select = &style->selectable;
14175 nk_zero_struct(*select);
14176 select->normal = nk_style_item_color(table[NK_COLOR_SELECT]);
14177 select->hover = nk_style_item_color(table[NK_COLOR_SELECT]);
14182 select->text_normal = table[NK_COLOR_TEXT];
14183 select->text_hover = table[NK_COLOR_TEXT];
14184 select->text_pressed = table[NK_COLOR_TEXT];
14185 select->text_normal_active = table[NK_COLOR_TEXT];
14186 select->text_hover_active = table[NK_COLOR_TEXT];
14187 select->text_pressed_active = table[NK_COLOR_TEXT];
14188 select->padding = nk_vec2(2.0f,2.0f);
14189 select->image_padding = nk_vec2(2.0f,2.0f);
14190 select->touch_padding = nk_vec2(0,0);
14191 select->userdata = nk_handle_ptr(0);
14192 select->rounding = 0.0f;
14193 select->draw_begin = 0;
14194 select->draw_end = 0;
14195
14196 /* slider */
14197 slider = &style->slider;
14198 nk_zero_struct(*slider);
14199 slider->normal = nk_style_item_hide();
14200 slider->hover = nk_style_item_hide();
14201 slider->active = nk_style_item_hide();
14202 slider->bar_normal = table[NK_COLOR_SLIDER];
14203 slider->bar_hover = table[NK_COLOR_SLIDER];
14204 slider->bar_active = table[NK_COLOR_SLIDER];
14205 slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR];
14211 slider->cursor_size = nk_vec2(16,16);
14212 slider->padding = nk_vec2(2,2);
14213 slider->spacing = nk_vec2(2,2);
14214 slider->userdata = nk_handle_ptr(0);
14215 slider->show_buttons = nk_false;
14216 slider->bar_height = 8;
14217 slider->rounding = 0;
14218 slider->draw_begin = 0;
14219 slider->draw_end = 0;
14220
14221 /* slider buttons */
14222 button = &style->slider.inc_button;
14223 button->normal = nk_style_item_color(nk_rgb(40,40,40));
14224 button->hover = nk_style_item_color(nk_rgb(42,42,42));
14225 button->active = nk_style_item_color(nk_rgb(44,44,44));
14226 button->border_color = nk_rgb(65,65,65);
14227 button->text_background = nk_rgb(40,40,40);
14228 button->text_normal = nk_rgb(175,175,175);
14229 button->text_hover = nk_rgb(175,175,175);
14230 button->text_active = nk_rgb(175,175,175);
14231 button->padding = nk_vec2(8.0f,8.0f);
14232 button->touch_padding = nk_vec2(0.0f,0.0f);
14233 button->userdata = nk_handle_ptr(0);
14235 button->border = 1.0f;
14236 button->rounding = 0.0f;
14237 button->draw_begin = 0;
14238 button->draw_end = 0;
14239 style->slider.dec_button = style->slider.inc_button;
14240
14241 /* progressbar */
14242 prog = &style->progress;
14243 nk_zero_struct(*prog);
14250 prog->border_color = nk_rgba(0,0,0,0);
14251 prog->cursor_border_color = nk_rgba(0,0,0,0);
14252 prog->userdata = nk_handle_ptr(0);
14253 prog->padding = nk_vec2(4,4);
14254 prog->rounding = 0;
14255 prog->border = 0;
14256 prog->cursor_rounding = 0;
14257 prog->cursor_border = 0;
14258 prog->draw_begin = 0;
14259 prog->draw_end = 0;
14260
14261 /* scrollbars */
14262 scroll = &style->scrollh;
14263 nk_zero_struct(*scroll);
14272 scroll->userdata = nk_handle_ptr(0);
14273 scroll->border_color = table[NK_COLOR_SCROLLBAR];
14274 scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
14275 scroll->padding = nk_vec2(0,0);
14276 scroll->show_buttons = nk_false;
14277 scroll->border = 0;
14278 scroll->rounding = 0;
14279 scroll->border_cursor = 0;
14280 scroll->rounding_cursor = 0;
14281 scroll->draw_begin = 0;
14282 scroll->draw_end = 0;
14283 style->scrollv = style->scrollh;
14284
14285 /* scrollbars buttons */
14286 button = &style->scrollh.inc_button;
14287 button->normal = nk_style_item_color(nk_rgb(40,40,40));
14288 button->hover = nk_style_item_color(nk_rgb(42,42,42));
14289 button->active = nk_style_item_color(nk_rgb(44,44,44));
14290 button->border_color = nk_rgb(65,65,65);
14291 button->text_background = nk_rgb(40,40,40);
14292 button->text_normal = nk_rgb(175,175,175);
14293 button->text_hover = nk_rgb(175,175,175);
14294 button->text_active = nk_rgb(175,175,175);
14295 button->padding = nk_vec2(4.0f,4.0f);
14296 button->touch_padding = nk_vec2(0.0f,0.0f);
14297 button->userdata = nk_handle_ptr(0);
14299 button->border = 1.0f;
14300 button->rounding = 0.0f;
14301 button->draw_begin = 0;
14302 button->draw_end = 0;
14303 style->scrollh.dec_button = style->scrollh.inc_button;
14304 style->scrollv.inc_button = style->scrollh.inc_button;
14305 style->scrollv.dec_button = style->scrollh.inc_button;
14306
14307 /* edit */
14308 edit = &style->edit;
14309 nk_zero_struct(*edit);
14311 edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]);
14313 edit->cursor_normal = table[NK_COLOR_TEXT];
14314 edit->cursor_hover = table[NK_COLOR_TEXT];
14315 edit->cursor_text_normal= table[NK_COLOR_EDIT];
14316 edit->cursor_text_hover = table[NK_COLOR_EDIT];
14317 edit->border_color = table[NK_COLOR_BORDER];
14318 edit->text_normal = table[NK_COLOR_TEXT];
14319 edit->text_hover = table[NK_COLOR_TEXT];
14320 edit->text_active = table[NK_COLOR_TEXT];
14321 edit->selected_normal = table[NK_COLOR_TEXT];
14322 edit->selected_hover = table[NK_COLOR_TEXT];
14323 edit->selected_text_normal = table[NK_COLOR_EDIT];
14324 edit->selected_text_hover = table[NK_COLOR_EDIT];
14325 edit->scrollbar_size = nk_vec2(10,10);
14326 edit->scrollbar = style->scrollv;
14327 edit->padding = nk_vec2(4,4);
14328 edit->row_padding = 2;
14329 edit->cursor_size = 4;
14330 edit->border = 1;
14331 edit->rounding = 0;
14332
14333 /* property */
14334 property = &style->property;
14335 nk_zero_struct(*property);
14336 property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14337 property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14338 property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14339 property->border_color = table[NK_COLOR_BORDER];
14340 property->label_normal = table[NK_COLOR_TEXT];
14341 property->label_hover = table[NK_COLOR_TEXT];
14342 property->label_active = table[NK_COLOR_TEXT];
14343 property->sym_left = NK_SYMBOL_TRIANGLE_LEFT;
14344 property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
14345 property->userdata = nk_handle_ptr(0);
14346 property->padding = nk_vec2(4,4);
14347 property->border = 1;
14348 property->rounding = 10;
14349 property->draw_begin = 0;
14350 property->draw_end = 0;
14351
14352 /* property buttons */
14353 button = &style->property.dec_button;
14354 nk_zero_struct(*button);
14358 button->border_color = nk_rgba(0,0,0,0);
14359 button->text_background = table[NK_COLOR_PROPERTY];
14360 button->text_normal = table[NK_COLOR_TEXT];
14361 button->text_hover = table[NK_COLOR_TEXT];
14362 button->text_active = table[NK_COLOR_TEXT];
14363 button->padding = nk_vec2(0.0f,0.0f);
14364 button->touch_padding = nk_vec2(0.0f,0.0f);
14365 button->userdata = nk_handle_ptr(0);
14367 button->border = 0.0f;
14368 button->rounding = 0.0f;
14369 button->draw_begin = 0;
14370 button->draw_end = 0;
14371 style->property.inc_button = style->property.dec_button;
14372
14373 /* property edit */
14374 edit = &style->property.edit;
14375 nk_zero_struct(*edit);
14379 edit->border_color = nk_rgba(0,0,0,0);
14380 edit->cursor_normal = table[NK_COLOR_TEXT];
14381 edit->cursor_hover = table[NK_COLOR_TEXT];
14382 edit->cursor_text_normal= table[NK_COLOR_EDIT];
14383 edit->cursor_text_hover = table[NK_COLOR_EDIT];
14384 edit->text_normal = table[NK_COLOR_TEXT];
14385 edit->text_hover = table[NK_COLOR_TEXT];
14386 edit->text_active = table[NK_COLOR_TEXT];
14387 edit->selected_normal = table[NK_COLOR_TEXT];
14388 edit->selected_hover = table[NK_COLOR_TEXT];
14389 edit->selected_text_normal = table[NK_COLOR_EDIT];
14390 edit->selected_text_hover = table[NK_COLOR_EDIT];
14391 edit->padding = nk_vec2(0,0);
14392 edit->cursor_size = 8;
14393 edit->border = 0;
14394 edit->rounding = 0;
14395
14396 /* chart */
14397 chart = &style->chart;
14398 nk_zero_struct(*chart);
14400 chart->border_color = table[NK_COLOR_BORDER];
14402 chart->color = table[NK_COLOR_CHART_COLOR];
14403 chart->padding = nk_vec2(4,4);
14404 chart->border = 0;
14405 chart->rounding = 0;
14406
14407 /* combo */
14408 combo = &style->combo;
14409 combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
14410 combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
14411 combo->active = nk_style_item_color(table[NK_COLOR_COMBO]);
14412 combo->border_color = table[NK_COLOR_BORDER];
14413 combo->label_normal = table[NK_COLOR_TEXT];
14414 combo->label_hover = table[NK_COLOR_TEXT];
14415 combo->label_active = table[NK_COLOR_TEXT];
14419 combo->content_padding = nk_vec2(4,4);
14420 combo->button_padding = nk_vec2(0,4);
14421 combo->spacing = nk_vec2(4,0);
14422 combo->border = 1;
14423 combo->rounding = 0;
14424
14425 /* combo button */
14426 button = &style->combo.button;
14427 nk_zero_struct(*button);
14428 button->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
14429 button->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
14430 button->active = nk_style_item_color(table[NK_COLOR_COMBO]);
14431 button->border_color = nk_rgba(0,0,0,0);
14432 button->text_background = table[NK_COLOR_COMBO];
14433 button->text_normal = table[NK_COLOR_TEXT];
14434 button->text_hover = table[NK_COLOR_TEXT];
14435 button->text_active = table[NK_COLOR_TEXT];
14436 button->padding = nk_vec2(2.0f,2.0f);
14437 button->touch_padding = nk_vec2(0.0f,0.0f);
14438 button->userdata = nk_handle_ptr(0);
14440 button->border = 0.0f;
14441 button->rounding = 0.0f;
14442 button->draw_begin = 0;
14443 button->draw_end = 0;
14444
14445 /* tab */
14446 tab = &style->tab;
14448 tab->border_color = table[NK_COLOR_BORDER];
14449 tab->text = table[NK_COLOR_TEXT];
14452 tab->padding = nk_vec2(4,4);
14453 tab->spacing = nk_vec2(4,4);
14454 tab->indent = 10.0f;
14455 tab->border = 1;
14456 tab->rounding = 0;
14457
14458 /* tab button */
14459 button = &style->tab.tab_minimize_button;
14460 nk_zero_struct(*button);
14464 button->border_color = nk_rgba(0,0,0,0);
14465 button->text_background = table[NK_COLOR_TAB_HEADER];
14466 button->text_normal = table[NK_COLOR_TEXT];
14467 button->text_hover = table[NK_COLOR_TEXT];
14468 button->text_active = table[NK_COLOR_TEXT];
14469 button->padding = nk_vec2(2.0f,2.0f);
14470 button->touch_padding = nk_vec2(0.0f,0.0f);
14471 button->userdata = nk_handle_ptr(0);
14473 button->border = 0.0f;
14474 button->rounding = 0.0f;
14475 button->draw_begin = 0;
14476 button->draw_end = 0;
14477 style->tab.tab_maximize_button =*button;
14478
14479 /* node button */
14480 button = &style->tab.node_minimize_button;
14481 nk_zero_struct(*button);
14482 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
14483 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
14484 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
14485 button->border_color = nk_rgba(0,0,0,0);
14486 button->text_background = table[NK_COLOR_TAB_HEADER];
14487 button->text_normal = table[NK_COLOR_TEXT];
14488 button->text_hover = table[NK_COLOR_TEXT];
14489 button->text_active = table[NK_COLOR_TEXT];
14490 button->padding = nk_vec2(2.0f,2.0f);
14491 button->touch_padding = nk_vec2(0.0f,0.0f);
14492 button->userdata = nk_handle_ptr(0);
14494 button->border = 0.0f;
14495 button->rounding = 0.0f;
14496 button->draw_begin = 0;
14497 button->draw_end = 0;
14498 style->tab.node_maximize_button =*button;
14499
14500 /* window header */
14501 win = &style->window;
14509 win->header.label_normal = table[NK_COLOR_TEXT];
14510 win->header.label_hover = table[NK_COLOR_TEXT];
14511 win->header.label_active = table[NK_COLOR_TEXT];
14512 win->header.label_padding = nk_vec2(4,4);
14513 win->header.padding = nk_vec2(4,4);
14514 win->header.spacing = nk_vec2(0,0);
14515
14516 /* window header close button */
14517 button = &style->window.header.close_button;
14518 nk_zero_struct(*button);
14519 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
14520 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
14521 button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
14522 button->border_color = nk_rgba(0,0,0,0);
14523 button->text_background = table[NK_COLOR_HEADER];
14524 button->text_normal = table[NK_COLOR_TEXT];
14525 button->text_hover = table[NK_COLOR_TEXT];
14526 button->text_active = table[NK_COLOR_TEXT];
14527 button->padding = nk_vec2(0.0f,0.0f);
14528 button->touch_padding = nk_vec2(0.0f,0.0f);
14529 button->userdata = nk_handle_ptr(0);
14531 button->border = 0.0f;
14532 button->rounding = 0.0f;
14533 button->draw_begin = 0;
14534 button->draw_end = 0;
14535
14536 /* window header minimize button */
14537 button = &style->window.header.minimize_button;
14538 nk_zero_struct(*button);
14539 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
14540 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
14541 button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
14542 button->border_color = nk_rgba(0,0,0,0);
14543 button->text_background = table[NK_COLOR_HEADER];
14544 button->text_normal = table[NK_COLOR_TEXT];
14545 button->text_hover = table[NK_COLOR_TEXT];
14546 button->text_active = table[NK_COLOR_TEXT];
14547 button->padding = nk_vec2(0.0f,0.0f);
14548 button->touch_padding = nk_vec2(0.0f,0.0f);
14549 button->userdata = nk_handle_ptr(0);
14551 button->border = 0.0f;
14552 button->rounding = 0.0f;
14553 button->draw_begin = 0;
14554 button->draw_end = 0;
14555
14556 /* window */
14557 win->background = table[NK_COLOR_WINDOW];
14559 win->border_color = table[NK_COLOR_BORDER];
14560 win->popup_border_color = table[NK_COLOR_BORDER];
14561 win->combo_border_color = table[NK_COLOR_BORDER];
14563 win->menu_border_color = table[NK_COLOR_BORDER];
14564 win->group_border_color = table[NK_COLOR_BORDER];
14567
14568 win->rounding = 0.0f;
14569 win->spacing = nk_vec2(4,4);
14570 win->scrollbar_size = nk_vec2(10,10);
14571 win->min_size = nk_vec2(64,64);
14572
14573 win->combo_border = 1.0f;
14574 win->contextual_border = 1.0f;
14575 win->menu_border = 1.0f;
14576 win->group_border = 1.0f;
14577 win->tooltip_border = 1.0f;
14578 win->popup_border = 1.0f;
14579 win->border = 2.0f;
14580 win->min_row_height_padding = 8;
14581
14582 win->padding = nk_vec2(4,4);
14583 win->group_padding = nk_vec2(4,4);
14584 win->popup_padding = nk_vec2(4,4);
14585 win->combo_padding = nk_vec2(4,4);
14586 win->contextual_padding = nk_vec2(4,4);
14587 win->menu_padding = nk_vec2(4,4);
14588 win->tooltip_padding = nk_vec2(4,4);
14589}
14590NK_API void
14591nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
14592{
14593 struct nk_style *style;
14594 NK_ASSERT(ctx);
14595
14596 if (!ctx) return;
14597 style = &ctx->style;
14598 style->font = font;
14599 ctx->stacks.fonts.head = 0;
14600 if (ctx->current)
14602}
14603NK_API int
14604nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
14605{
14606 struct nk_config_stack_user_font *font_stack;
14607 struct nk_config_stack_user_font_element *element;
14608
14609 NK_ASSERT(ctx);
14610 if (!ctx) return 0;
14611
14612 font_stack = &ctx->stacks.fonts;
14613 NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
14614 if (font_stack->head >= (int)NK_LEN(font_stack->elements))
14615 return 0;
14616
14617 element = &font_stack->elements[font_stack->head++];
14618 element->address = &ctx->style.font;
14619 element->old_value = ctx->style.font;
14620 ctx->style.font = font;
14621 return 1;
14622}
14623NK_API int
14624nk_style_pop_font(struct nk_context *ctx)
14625{
14626 struct nk_config_stack_user_font *font_stack;
14627 struct nk_config_stack_user_font_element *element;
14628
14629 NK_ASSERT(ctx);
14630 if (!ctx) return 0;
14631
14632 font_stack = &ctx->stacks.fonts;
14633 NK_ASSERT(font_stack->head > 0);
14634 if (font_stack->head < 1)
14635 return 0;
14636
14637 element = &font_stack->elements[--font_stack->head];
14638 *element->address = element->old_value;
14639 return 1;
14640}
14641#define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
14642nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
14643{\
14644 struct nk_config_stack_##type * type_stack;\
14645 struct nk_config_stack_##type##_element *element;\
14646 NK_ASSERT(ctx);\
14647 if (!ctx) return 0;\
14648 type_stack = &ctx->stacks.stack;\
14649 NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
14650 if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
14651 return 0;\
14652 element = &type_stack->elements[type_stack->head++];\
14653 element->address = address;\
14654 element->old_value = *address;\
14655 *address = value;\
14656 return 1;\
14657}
14658#define NK_STYLE_POP_IMPLEMENATION(type, stack) \
14659nk_style_pop_##type(struct nk_context *ctx)\
14660{\
14661 struct nk_config_stack_##type *type_stack;\
14662 struct nk_config_stack_##type##_element *element;\
14663 NK_ASSERT(ctx);\
14664 if (!ctx) return 0;\
14665 type_stack = &ctx->stacks.stack;\
14666 NK_ASSERT(type_stack->head > 0);\
14667 if (type_stack->head < 1)\
14668 return 0;\
14669 element = &type_stack->elements[--type_stack->head];\
14670 *element->address = element->old_value;\
14671 return 1;\
14672}
14673NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
14674NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
14675NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
14676NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
14677NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
14678
14679NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
14680NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
14681NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
14682NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
14683NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
14684
14685NK_API int
14687{
14688 struct nk_style *style;
14689 NK_ASSERT(ctx);
14690 if (!ctx) return 0;
14691 style = &ctx->style;
14692 if (style->cursors[c]) {
14693 style->cursor_active = style->cursors[c];
14694 return 1;
14695 }
14696 return 0;
14697}
14698NK_API void
14700{
14702}
14703NK_API void
14705{
14707}
14708NK_API void
14709nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
14710 const struct nk_cursor *c)
14711{
14712 struct nk_style *style;
14713 NK_ASSERT(ctx);
14714 if (!ctx) return;
14715 style = &ctx->style;
14716 style->cursors[cursor] = c;
14717}
14718NK_API void
14720{
14721 int i = 0;
14722 struct nk_style *style;
14723 NK_ASSERT(ctx);
14724 if (!ctx) return;
14725 style = &ctx->style;
14726 for (i = 0; i < NK_CURSOR_COUNT; ++i)
14727 style->cursors[i] = &cursors[i];
14728 style->cursor_visible = nk_true;
14729}
14730
14731
14732
14733
14734/* ==============================================================
14735 *
14736 * CONTEXT
14737 *
14738 * ===============================================================*/
14739NK_INTERN void
14740nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
14741{
14742 NK_ASSERT(ctx);
14743 if (!ctx) return;
14744 nk_zero_struct(*ctx);
14745 nk_style_default(ctx);
14746 ctx->seq = 1;
14747 if (font) ctx->style.font = font;
14748#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
14749 nk_draw_list_init(&ctx->draw_list);
14750#endif
14751}
14752#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
14753NK_API int
14754nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
14755{
14756 struct nk_allocator alloc;
14757 alloc.userdata.ptr = 0;
14758 alloc.alloc = nk_malloc;
14759 alloc.free = nk_mfree;
14760 return nk_init(ctx, &alloc, font);
14761}
14762#endif
14763NK_API int
14764nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
14765 const struct nk_user_font *font)
14766{
14767 NK_ASSERT(memory);
14768 if (!memory) return 0;
14769 nk_setup(ctx, font);
14770 nk_buffer_init_fixed(&ctx->memory, memory, size);
14771 ctx->use_pool = nk_false;
14772 return 1;
14773}
14774NK_API int
14775nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
14776 struct nk_buffer *pool, const struct nk_user_font *font)
14777{
14778 NK_ASSERT(cmds);
14779 NK_ASSERT(pool);
14780 if (!cmds || !pool) return 0;
14781
14782 nk_setup(ctx, font);
14783 ctx->memory = *cmds;
14784 if (pool->type == NK_BUFFER_FIXED) {
14785 /* take memory from buffer and alloc fixed pool */
14786 nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
14787 } else {
14788 /* create dynamic pool from buffer allocator */
14789 struct nk_allocator *alloc = &pool->pool;
14790 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
14791 }
14792 ctx->use_pool = nk_true;
14793 return 1;
14794}
14795NK_API int
14796nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
14797 const struct nk_user_font *font)
14798{
14799 NK_ASSERT(alloc);
14800 if (!alloc) return 0;
14801 nk_setup(ctx, font);
14802 nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
14803 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
14804 ctx->use_pool = nk_true;
14805 return 1;
14806}
14807#ifdef NK_INCLUDE_COMMAND_USERDATA
14808NK_API void
14809nk_set_user_data(struct nk_context *ctx, nk_handle handle)
14810{
14811 if (!ctx) return;
14812 ctx->userdata = handle;
14813 if (ctx->current)
14814 ctx->current->buffer.userdata = handle;
14815}
14816#endif
14817NK_API void
14818nk_free(struct nk_context *ctx)
14819{
14820 NK_ASSERT(ctx);
14821 if (!ctx) return;
14822 nk_buffer_free(&ctx->memory);
14823 if (ctx->use_pool)
14824 nk_pool_free(&ctx->pool);
14825
14826 nk_zero(&ctx->input, sizeof(ctx->input));
14827 nk_zero(&ctx->style, sizeof(ctx->style));
14828 nk_zero(&ctx->memory, sizeof(ctx->memory));
14829
14830 ctx->seq = 0;
14831 ctx->build = 0;
14832 ctx->begin = 0;
14833 ctx->end = 0;
14834 ctx->active = 0;
14835 ctx->current = 0;
14836 ctx->freelist = 0;
14837 ctx->count = 0;
14838}
14839NK_API void
14840nk_clear(struct nk_context *ctx)
14841{
14842 struct nk_window *iter;
14843 struct nk_window *next;
14844 NK_ASSERT(ctx);
14845
14846 if (!ctx) return;
14847 if (ctx->use_pool)
14848 nk_buffer_clear(&ctx->memory);
14850
14851 ctx->build = 0;
14852 ctx->memory.calls = 0;
14853 ctx->last_widget_state = 0;
14855 NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
14856
14857 /* garbage collector */
14858 iter = ctx->begin;
14859 while (iter) {
14860 /* make sure valid minimized windows do not get removed */
14861 if ((iter->flags & NK_WINDOW_MINIMIZED) &&
14862 !(iter->flags & NK_WINDOW_CLOSED) &&
14863 iter->seq == ctx->seq) {
14864 iter = iter->next;
14865 continue;
14866 }
14867 /* remove hotness from hidden or closed windows*/
14868 if (((iter->flags & NK_WINDOW_HIDDEN) ||
14869 (iter->flags & NK_WINDOW_CLOSED)) &&
14870 iter == ctx->active) {
14871 ctx->active = iter->prev;
14872 ctx->end = iter->prev;
14873 if (!ctx->end)
14874 ctx->begin = 0;
14875 if (ctx->active)
14876 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
14877 }
14878 /* free unused popup windows */
14879 if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
14880 nk_free_window(ctx, iter->popup.win);
14881 iter->popup.win = 0;
14882 }
14883 /* remove unused window state tables */
14884 {struct nk_table *n, *it = iter->tables;
14885 while (it) {
14886 n = it->next;
14887 if (it->seq != ctx->seq) {
14888 nk_remove_table(iter, it);
14889 nk_zero(it, sizeof(union nk_page_data));
14890 nk_free_table(ctx, it);
14891 if (it == iter->tables)
14892 iter->tables = n;
14893 } it = n;
14894 }}
14895 /* window itself is not used anymore so free */
14896 if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
14897 next = iter->next;
14898 nk_remove_window(ctx, iter);
14899 nk_free_window(ctx, iter);
14900 iter = next;
14901 } else iter = iter->next;
14902 }
14903 ctx->seq++;
14904}
14905NK_LIB void
14906nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
14907{
14908 NK_ASSERT(ctx);
14909 NK_ASSERT(buffer);
14910 if (!ctx || !buffer) return;
14911 buffer->begin = ctx->memory.allocated;
14912 buffer->end = buffer->begin;
14913 buffer->last = buffer->begin;
14914 buffer->clip = nk_null_rect;
14915}
14916NK_LIB void
14917nk_start(struct nk_context *ctx, struct nk_window *win)
14918{
14919 NK_ASSERT(ctx);
14920 NK_ASSERT(win);
14921 nk_start_buffer(ctx, &win->buffer);
14922}
14923NK_LIB void
14924nk_start_popup(struct nk_context *ctx, struct nk_window *win)
14925{
14926 struct nk_popup_buffer *buf;
14927 NK_ASSERT(ctx);
14928 NK_ASSERT(win);
14929 if (!ctx || !win) return;
14930
14931 /* save buffer fill state for popup */
14932 buf = &win->popup.buf;
14933 buf->begin = win->buffer.end;
14934 buf->end = win->buffer.end;
14935 buf->parent = win->buffer.last;
14936 buf->last = buf->begin;
14937 buf->active = nk_true;
14938}
14939NK_LIB void
14940nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
14941{
14942 struct nk_popup_buffer *buf;
14943 NK_ASSERT(ctx);
14944 NK_ASSERT(win);
14945 if (!ctx || !win) return;
14946
14947 buf = &win->popup.buf;
14948 buf->last = win->buffer.last;
14949 buf->end = win->buffer.end;
14950}
14951NK_LIB void
14952nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
14953{
14954 NK_ASSERT(ctx);
14955 NK_ASSERT(buffer);
14956 if (!ctx || !buffer) return;
14957 buffer->end = ctx->memory.allocated;
14958}
14959NK_LIB void
14960nk_finish(struct nk_context *ctx, struct nk_window *win)
14961{
14962 struct nk_popup_buffer *buf;
14963 struct nk_command *parent_last;
14964 void *memory;
14965
14966 NK_ASSERT(ctx);
14967 NK_ASSERT(win);
14968 if (!ctx || !win) return;
14969 nk_finish_buffer(ctx, &win->buffer);
14970 if (!win->popup.buf.active) return;
14971
14972 buf = &win->popup.buf;
14973 memory = ctx->memory.memory.ptr;
14974 parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
14975 parent_last->next = buf->end;
14976}
14977NK_LIB void
14978nk_build(struct nk_context *ctx)
14979{
14980 struct nk_window *it = 0;
14981 struct nk_command *cmd = 0;
14982 nk_byte *buffer = 0;
14983
14984 /* draw cursor overlay */
14985 if (!ctx->style.cursor_active)
14987 if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
14988 struct nk_rect mouse_bounds;
14989 const struct nk_cursor *cursor = ctx->style.cursor_active;
14990 nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
14991 nk_start_buffer(ctx, &ctx->overlay);
14992
14993 mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
14994 mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
14995 mouse_bounds.w = cursor->size.x;
14996 mouse_bounds.h = cursor->size.y;
14997
14998 nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
14999 nk_finish_buffer(ctx, &ctx->overlay);
15000 }
15001 /* build one big draw command list out of all window buffers */
15002 it = ctx->begin;
15003 buffer = (nk_byte*)ctx->memory.memory.ptr;
15004 while (it != 0) {
15005 struct nk_window *next = it->next;
15006 if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
15007 it->seq != ctx->seq)
15008 goto cont;
15009
15010 cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
15011 while (next && ((next->buffer.last == next->buffer.begin) ||
15012 (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq))
15013 next = next->next; /* skip empty command buffers */
15014
15015 if (next) cmd->next = next->buffer.begin;
15016 cont: it = next;
15017 }
15018 /* append all popup draw commands into lists */
15019 it = ctx->begin;
15020 while (it != 0) {
15021 struct nk_window *next = it->next;
15022 struct nk_popup_buffer *buf;
15023 if (!it->popup.buf.active)
15024 goto skip;
15025
15026 buf = &it->popup.buf;
15027 cmd->next = buf->begin;
15028 cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
15029 buf->active = nk_false;
15030 skip: it = next;
15031 }
15032 if (cmd) {
15033 /* append overlay commands */
15034 if (ctx->overlay.end != ctx->overlay.begin)
15035 cmd->next = ctx->overlay.begin;
15036 else cmd->next = ctx->memory.allocated;
15037 }
15038}
15039NK_API const struct nk_command*
15040nk__begin(struct nk_context *ctx)
15041{
15042 struct nk_window *iter;
15043 nk_byte *buffer;
15044 NK_ASSERT(ctx);
15045 if (!ctx) return 0;
15046 if (!ctx->count) return 0;
15047
15048 buffer = (nk_byte*)ctx->memory.memory.ptr;
15049 if (!ctx->build) {
15050 nk_build(ctx);
15051 ctx->build = nk_true;
15052 }
15053 iter = ctx->begin;
15054 while (iter && ((iter->buffer.begin == iter->buffer.end) ||
15055 (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
15056 iter = iter->next;
15057 if (!iter) return 0;
15058 return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
15059}
15060
15061NK_API const struct nk_command*
15062nk__next(struct nk_context *ctx, const struct nk_command *cmd)
15063{
15064 nk_byte *buffer;
15065 const struct nk_command *next;
15066 NK_ASSERT(ctx);
15067 if (!ctx || !cmd || !ctx->count) return 0;
15068 if (cmd->next >= ctx->memory.allocated) return 0;
15069 buffer = (nk_byte*)ctx->memory.memory.ptr;
15070 next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
15071 return next;
15072}
15073
15074
15075
15076
15077
15078/* ===============================================================
15079 *
15080 * POOL
15081 *
15082 * ===============================================================*/
15083NK_LIB void
15084nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
15085 unsigned int capacity)
15086{
15087 nk_zero(pool, sizeof(*pool));
15088 pool->alloc = *alloc;
15089 pool->capacity = capacity;
15090 pool->type = NK_BUFFER_DYNAMIC;
15091 pool->pages = 0;
15092}
15093NK_LIB void
15094nk_pool_free(struct nk_pool *pool)
15095{
15096 struct nk_page *iter = pool->pages;
15097 if (!pool) return;
15098 if (pool->type == NK_BUFFER_FIXED) return;
15099 while (iter) {
15100 struct nk_page *next = iter->next;
15101 pool->alloc.free(pool->alloc.userdata, iter);
15102 iter = next;
15103 }
15104}
15105NK_LIB void
15106nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
15107{
15108 nk_zero(pool, sizeof(*pool));
15109 NK_ASSERT(size >= sizeof(struct nk_page));
15110 if (size < sizeof(struct nk_page)) return;
15111 pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
15112 pool->pages = (struct nk_page*)memory;
15113 pool->type = NK_BUFFER_FIXED;
15114 pool->size = size;
15115}
15116NK_LIB struct nk_page_element*
15117nk_pool_alloc(struct nk_pool *pool)
15118{
15119 if (!pool->pages || pool->pages->size >= pool->capacity) {
15120 /* allocate new page */
15121 struct nk_page *page;
15122 if (pool->type == NK_BUFFER_FIXED) {
15123 NK_ASSERT(pool->pages);
15124 if (!pool->pages) return 0;
15125 NK_ASSERT(pool->pages->size < pool->capacity);
15126 return 0;
15127 } else {
15128 nk_size size = sizeof(struct nk_page);
15129 size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
15130 page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
15131 page->next = pool->pages;
15132 pool->pages = page;
15133 page->size = 0;
15134 }
15135 } return &pool->pages->win[pool->pages->size++];
15136}
15137
15138
15139
15140
15141/* ===============================================================
15142 *
15143 * PAGE ELEMENT
15144 *
15145 * ===============================================================*/
15146NK_LIB struct nk_page_element*
15147nk_create_page_element(struct nk_context *ctx)
15148{
15149 struct nk_page_element *elem;
15150 if (ctx->freelist) {
15151 /* unlink page element from free list */
15152 elem = ctx->freelist;
15153 ctx->freelist = elem->next;
15154 } else if (ctx->use_pool) {
15155 /* allocate page element from memory pool */
15156 elem = nk_pool_alloc(&ctx->pool);
15157 NK_ASSERT(elem);
15158 if (!elem) return 0;
15159 } else {
15160 /* allocate new page element from back of fixed size memory buffer */
15161 NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
15162 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
15163 elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
15164 NK_ASSERT(elem);
15165 if (!elem) return 0;
15166 }
15167 nk_zero_struct(*elem);
15168 elem->next = 0;
15169 elem->prev = 0;
15170 return elem;
15171}
15172NK_LIB void
15173nk_link_page_element_into_freelist(struct nk_context *ctx,
15174 struct nk_page_element *elem)
15175{
15176 /* link table into freelist */
15177 if (!ctx->freelist) {
15178 ctx->freelist = elem;
15179 } else {
15180 elem->next = ctx->freelist;
15181 ctx->freelist = elem;
15182 }
15183}
15184NK_LIB void
15185nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
15186{
15187 /* we have a pool so just add to free list */
15188 if (ctx->use_pool) {
15189 nk_link_page_element_into_freelist(ctx, elem);
15190 return;
15191 }
15192 /* if possible remove last element from back of fixed memory buffer */
15193 {void *elem_end = (void*)(elem + 1);
15194 void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
15195 if (elem_end == buffer_end)
15196 ctx->memory.size -= sizeof(struct nk_page_element);
15197 else nk_link_page_element_into_freelist(ctx, elem);}
15198}
15199
15200
15201
15202
15203/* ===============================================================
15204 *
15205 * TABLE
15206 *
15207 * ===============================================================*/
15208NK_LIB struct nk_table*
15209nk_create_table(struct nk_context *ctx)
15210{
15211 struct nk_page_element *elem;
15212 elem = nk_create_page_element(ctx);
15213 if (!elem) return 0;
15214 nk_zero_struct(*elem);
15215 return &elem->data.tbl;
15216}
15217NK_LIB void
15218nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
15219{
15220 union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
15221 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
15222 nk_free_page_element(ctx, pe);
15223}
15224NK_LIB void
15225nk_push_table(struct nk_window *win, struct nk_table *tbl)
15226{
15227 if (!win->tables) {
15228 win->tables = tbl;
15229 tbl->next = 0;
15230 tbl->prev = 0;
15231 tbl->size = 0;
15232 win->table_count = 1;
15233 return;
15234 }
15235 win->tables->prev = tbl;
15236 tbl->next = win->tables;
15237 tbl->prev = 0;
15238 tbl->size = 0;
15239 win->tables = tbl;
15240 win->table_count++;
15241}
15242NK_LIB void
15243nk_remove_table(struct nk_window *win, struct nk_table *tbl)
15244{
15245 if (win->tables == tbl)
15246 win->tables = tbl->next;
15247 if (tbl->next)
15248 tbl->next->prev = tbl->prev;
15249 if (tbl->prev)
15250 tbl->prev->next = tbl->next;
15251 tbl->next = 0;
15252 tbl->prev = 0;
15253}
15255nk_add_value(struct nk_context *ctx, struct nk_window *win,
15256 nk_hash name, nk_uint value)
15257{
15258 NK_ASSERT(ctx);
15259 NK_ASSERT(win);
15260 if (!win || !ctx) return 0;
15261 if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
15262 struct nk_table *tbl = nk_create_table(ctx);
15263 NK_ASSERT(tbl);
15264 if (!tbl) return 0;
15265 nk_push_table(win, tbl);
15266 }
15267 win->tables->seq = win->seq;
15268 win->tables->keys[win->tables->size] = name;
15269 win->tables->values[win->tables->size] = value;
15270 return &win->tables->values[win->tables->size++];
15271}
15273nk_find_value(struct nk_window *win, nk_hash name)
15274{
15275 struct nk_table *iter = win->tables;
15276 while (iter) {
15277 unsigned int i = 0;
15278 unsigned int size = iter->size;
15279 for (i = 0; i < size; ++i) {
15280 if (iter->keys[i] == name) {
15281 iter->seq = win->seq;
15282 return &iter->values[i];
15283 }
15285 iter = iter->next;
15286 }
15287 return 0;
15288}
15289
15290
15291
15292
15293/* ===============================================================
15294 *
15295 * PANEL
15296 *
15297 * ===============================================================*/
15298NK_LIB void*
15299nk_create_panel(struct nk_context *ctx)
15300{
15301 struct nk_page_element *elem;
15302 elem = nk_create_page_element(ctx);
15303 if (!elem) return 0;
15304 nk_zero_struct(*elem);
15305 return &elem->data.pan;
15306}
15307NK_LIB void
15308nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
15309{
15310 union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
15311 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
15312 nk_free_page_element(ctx, pe);
15313}
15314NK_LIB int
15315nk_panel_has_header(nk_flags flags, const char *title)
15316{
15317 int active = 0;
15318 active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
15319 active = active || (flags & NK_WINDOW_TITLE);
15320 active = active && !(flags & NK_WINDOW_HIDDEN) && title;
15321 return active;
15322}
15323NK_LIB struct nk_vec2
15324nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
15325{
15326 switch (type) {
15327 default:
15328 case NK_PANEL_WINDOW: return style->window.padding;
15329 case NK_PANEL_GROUP: return style->window.group_padding;
15330 case NK_PANEL_POPUP: return style->window.popup_padding;
15331 case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
15332 case NK_PANEL_COMBO: return style->window.combo_padding;
15333 case NK_PANEL_MENU: return style->window.menu_padding;
15334 case NK_PANEL_TOOLTIP: return style->window.menu_padding;}
15335}
15336NK_LIB float
15337nk_panel_get_border(const struct nk_style *style, nk_flags flags,
15338 enum nk_panel_type type)
15339{
15340 if (flags & NK_WINDOW_BORDER) {
15341 switch (type) {
15342 default:
15343 case NK_PANEL_WINDOW: return style->window.border;
15344 case NK_PANEL_GROUP: return style->window.group_border;
15345 case NK_PANEL_POPUP: return style->window.popup_border;
15346 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
15347 case NK_PANEL_COMBO: return style->window.combo_border;
15348 case NK_PANEL_MENU: return style->window.menu_border;
15349 case NK_PANEL_TOOLTIP: return style->window.menu_border;
15350 }} else return 0;
15351}
15352NK_LIB struct nk_color
15353nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
15354{
15355 switch (type) {
15356 default:
15357 case NK_PANEL_WINDOW: return style->window.border_color;
15358 case NK_PANEL_GROUP: return style->window.group_border_color;
15359 case NK_PANEL_POPUP: return style->window.popup_border_color;
15360 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
15361 case NK_PANEL_COMBO: return style->window.combo_border_color;
15362 case NK_PANEL_MENU: return style->window.menu_border_color;
15363 case NK_PANEL_TOOLTIP: return style->window.menu_border_color;}
15364}
15365NK_LIB int
15366nk_panel_is_sub(enum nk_panel_type type)
15367{
15368 return (type & NK_PANEL_SET_SUB)?1:0;
15369}
15370NK_LIB int
15371nk_panel_is_nonblock(enum nk_panel_type type)
15372{
15373 return (type & NK_PANEL_SET_NONBLOCK)?1:0;
15374}
15375NK_LIB int
15376nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
15377{
15378 struct nk_input *in;
15379 struct nk_window *win;
15380 struct nk_panel *layout;
15381 struct nk_command_buffer *out;
15382 const struct nk_style *style;
15383 const struct nk_user_font *font;
15384
15385 struct nk_vec2 scrollbar_size;
15386 struct nk_vec2 panel_padding;
15387
15388 NK_ASSERT(ctx);
15389 NK_ASSERT(ctx->current);
15390 NK_ASSERT(ctx->current->layout);
15391 if (!ctx || !ctx->current || !ctx->current->layout) return 0;
15392 nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
15393 if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
15394 nk_zero(ctx->current->layout, sizeof(struct nk_panel));
15395 ctx->current->layout->type = panel_type;
15396 return 0;
15397 }
15398 /* pull state into local stack */
15399 style = &ctx->style;
15400 font = style->font;
15401 win = ctx->current;
15402 layout = win->layout;
15403 out = &win->buffer;
15404 in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
15405#ifdef NK_INCLUDE_COMMAND_USERDATA
15406 win->buffer.userdata = ctx->userdata;
15407#endif
15408 /* pull style configuration into local stack */
15409 scrollbar_size = style->window.scrollbar_size;
15410 panel_padding = nk_panel_get_padding(style, panel_type);
15411
15412 /* window movement */
15413 if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
15414 int left_mouse_down;
15415 int left_mouse_clicked;
15416 int left_mouse_click_in_cursor;
15417
15418 /* calculate draggable window space */
15419 struct nk_rect header;
15420 header.x = win->bounds.x;
15421 header.y = win->bounds.y;
15422 header.w = win->bounds.w;
15423 if (nk_panel_has_header(win->flags, title)) {
15424 header.h = font->height + 2.0f * style->window.header.padding.y;
15425 header.h += 2.0f * style->window.header.label_padding.y;
15426 } else header.h = panel_padding.y;
15427
15428 /* window movement by dragging */
15429 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
15430 left_mouse_clicked = (int)in->mouse.buttons[NK_BUTTON_LEFT].clicked;
15431 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
15432 NK_BUTTON_LEFT, header, nk_true);
15433 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
15434 win->bounds.x = win->bounds.x + in->mouse.delta.x;
15435 win->bounds.y = win->bounds.y + in->mouse.delta.y;
15439 }
15440 }
15441
15442 /* setup panel */
15443 layout->type = panel_type;
15444 layout->flags = win->flags;
15445 layout->bounds = win->bounds;
15446 layout->bounds.x += panel_padding.x;
15447 layout->bounds.w -= 2*panel_padding.x;
15448 if (win->flags & NK_WINDOW_BORDER) {
15449 layout->border = nk_panel_get_border(style, win->flags, panel_type);
15450 layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
15451 } else layout->border = 0;
15452 layout->at_y = layout->bounds.y;
15453 layout->at_x = layout->bounds.x;
15454 layout->max_x = 0;
15455 layout->header_height = 0;
15456 layout->footer_height = 0;
15458 layout->row.index = 0;
15459 layout->row.columns = 0;
15460 layout->row.ratio = 0;
15461 layout->row.item_width = 0;
15462 layout->row.tree_depth = 0;
15463 layout->row.height = panel_padding.y;
15464 layout->has_scrolling = nk_true;
15465 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
15466 layout->bounds.w -= scrollbar_size.x;
15467 if (!nk_panel_is_nonblock(panel_type)) {
15468 layout->footer_height = 0;
15469 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
15470 layout->footer_height = scrollbar_size.y;
15471 layout->bounds.h -= layout->footer_height;
15472 }
15473
15474 /* panel header */
15475 if (nk_panel_has_header(win->flags, title))
15476 {
15477 struct nk_text text;
15478 struct nk_rect header;
15479 const struct nk_style_item *background = 0;
15480
15481 /* calculate header bounds */
15482 header.x = win->bounds.x;
15483 header.y = win->bounds.y;
15484 header.w = win->bounds.w;
15485 header.h = font->height + 2.0f * style->window.header.padding.y;
15486 header.h += (2.0f * style->window.header.label_padding.y);
15487
15488 /* shrink panel by header */
15489 layout->header_height = header.h;
15490 layout->bounds.y += header.h;
15491 layout->bounds.h -= header.h;
15492 layout->at_y += header.h;
15493
15494 /* select correct header background and text color */
15495 if (ctx->active == win) {
15496 background = &style->window.header.active;
15497 text.text = style->window.header.label_active;
15498 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
15499 background = &style->window.header.hover;
15500 text.text = style->window.header.label_hover;
15501 } else {
15502 background = &style->window.header.normal;
15503 text.text = style->window.header.label_normal;
15504 }
15505
15506 /* draw header background */
15507 header.h += 1.0f;
15508 if (background->type == NK_STYLE_ITEM_IMAGE) {
15509 text.background = nk_rgba(0,0,0,0);
15510 nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
15511 } else {
15512 text.background = background->data.color;
15513 nk_fill_rect(out, header, 0, background->data.color);
15514 }
15515
15516 /* window close button */
15517 {struct nk_rect button;
15518 button.y = header.y + style->window.header.padding.y;
15519 button.h = header.h - 2 * style->window.header.padding.y;
15520 button.w = button.h;
15521 if (win->flags & NK_WINDOW_CLOSABLE) {
15522 nk_flags ws = 0;
15523 if (style->window.header.align == NK_HEADER_RIGHT) {
15524 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
15525 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
15526 } else {
15527 button.x = header.x + style->window.header.padding.x;
15528 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
15529 }
15530
15531 if (nk_do_button_symbol(&ws, &win->buffer, button,
15533 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
15534 {
15535 layout->flags |= NK_WINDOW_HIDDEN;
15536 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
15537 }
15538 }
15539
15540 /* window minimize button */
15541 if (win->flags & NK_WINDOW_MINIMIZABLE) {
15542 nk_flags ws = 0;
15543 if (style->window.header.align == NK_HEADER_RIGHT) {
15544 button.x = (header.w + header.x) - button.w;
15545 if (!(win->flags & NK_WINDOW_CLOSABLE)) {
15546 button.x -= style->window.header.padding.x;
15547 header.w -= style->window.header.padding.x;
15548 }
15549 header.w -= button.w + style->window.header.spacing.x;
15550 } else {
15551 button.x = header.x;
15552 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
15553 }
15554 if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
15556 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
15557 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
15559 layout->flags | NK_WINDOW_MINIMIZED;
15560 }}
15561
15562 {/* window header title */
15563 int text_len = nk_strlen(title);
15564 struct nk_rect label = {0,0,0,0};
15565 float t = font->width(font->userdata, font->height, title, text_len);
15566 text.padding = nk_vec2(0,0);
15567
15568 label.x = header.x + style->window.header.padding.x;
15569 label.x += style->window.header.label_padding.x;
15570 label.y = header.y + style->window.header.label_padding.y;
15571 label.h = font->height + 2 * style->window.header.label_padding.y;
15572 label.w = t + 2 * style->window.header.spacing.x;
15573 label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
15574 nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
15575 }
15576
15577 /* draw window background */
15578 if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
15579 struct nk_rect body;
15580 body.x = win->bounds.x;
15581 body.w = win->bounds.w;
15582 body.y = (win->bounds.y + layout->header_height);
15583 body.h = (win->bounds.h - layout->header_height);
15585 nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
15586 else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
15587 }
15588
15589 /* set clipping rectangle */
15590 {struct nk_rect clip;
15591 layout->clip = layout->bounds;
15592 nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
15593 layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
15594 nk_push_scissor(out, clip);
15595 layout->clip = clip;}
15596 return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
15597}
15598NK_LIB void
15599nk_panel_end(struct nk_context *ctx)
15600{
15601 struct nk_input *in;
15602 struct nk_window *window;
15603 struct nk_panel *layout;
15604 const struct nk_style *style;
15605 struct nk_command_buffer *out;
15606
15607 struct nk_vec2 scrollbar_size;
15608 struct nk_vec2 panel_padding;
15609
15610 NK_ASSERT(ctx);
15611 NK_ASSERT(ctx->current);
15612 NK_ASSERT(ctx->current->layout);
15613 if (!ctx || !ctx->current || !ctx->current->layout)
15614 return;
15615
15616 window = ctx->current;
15617 layout = window->layout;
15618 style = &ctx->style;
15619 out = &window->buffer;
15620 in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
15621 if (!nk_panel_is_sub(layout->type))
15622 nk_push_scissor(out, nk_null_rect);
15623
15624 /* cache configuration data */
15625 scrollbar_size = style->window.scrollbar_size;
15626 panel_padding = nk_panel_get_padding(style, layout->type);
15627
15628 /* update the current cursor Y-position to point over the last added widget */
15629 layout->at_y += layout->row.height;
15630
15631 /* dynamic panels */
15632 if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
15633 {
15634 /* update panel height to fit dynamic growth */
15635 struct nk_rect empty_space;
15636 if (layout->at_y < (layout->bounds.y + layout->bounds.h))
15637 layout->bounds.h = layout->at_y - layout->bounds.y;
15638
15639 /* fill top empty space */
15640 empty_space.x = window->bounds.x;
15641 empty_space.y = layout->bounds.y;
15642 empty_space.h = panel_padding.y;
15643 empty_space.w = window->bounds.w;
15644 nk_fill_rect(out, empty_space, 0, style->window.background);
15645
15646 /* fill left empty space */
15647 empty_space.x = window->bounds.x;
15648 empty_space.y = layout->bounds.y;
15649 empty_space.w = panel_padding.x + layout->border;
15650 empty_space.h = layout->bounds.h;
15651 nk_fill_rect(out, empty_space, 0, style->window.background);
15652
15653 /* fill right empty space */
15654 empty_space.x = layout->bounds.x + layout->bounds.w;
15655 empty_space.y = layout->bounds.y;
15656 empty_space.w = panel_padding.x + layout->border;
15657 empty_space.h = layout->bounds.h;
15658 if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
15659 empty_space.w += scrollbar_size.x;
15660 nk_fill_rect(out, empty_space, 0, style->window.background);
15661
15662 /* fill bottom empty space */
15663 if (layout->footer_height > 0) {
15664 empty_space.x = window->bounds.x;
15665 empty_space.y = layout->bounds.y + layout->bounds.h;
15666 empty_space.w = window->bounds.w;
15667 empty_space.h = layout->footer_height;
15668 nk_fill_rect(out, empty_space, 0, style->window.background);
15669 }
15670 }
15671
15672 /* scrollbars */
15673 if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
15674 !(layout->flags & NK_WINDOW_MINIMIZED) &&
15676 {
15677 struct nk_rect scroll;
15678 int scroll_has_scrolling;
15679 float scroll_target;
15680 float scroll_offset;
15681 float scroll_step;
15682 float scroll_inc;
15683
15684 /* mouse wheel scrolling */
15685 if (nk_panel_is_sub(layout->type))
15686 {
15687 /* sub-window mouse wheel scrolling */
15688 struct nk_window *root_window = window;
15689 struct nk_panel *root_panel = window->layout;
15690 while (root_panel->parent)
15691 root_panel = root_panel->parent;
15692 while (root_window->parent)
15693 root_window = root_window->parent;
15694
15695 /* only allow scrolling if parent window is active */
15696 scroll_has_scrolling = 0;
15697 if ((root_window == ctx->active) && layout->has_scrolling) {
15698 /* and panel is being hovered and inside clip rect*/
15699 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
15700 NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
15701 root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
15702 {
15703 /* deactivate all parent scrolling */
15704 root_panel = window->layout;
15705 while (root_panel->parent) {
15706 root_panel->has_scrolling = nk_false;
15707 root_panel = root_panel->parent;
15708 }
15709 root_panel->has_scrolling = nk_false;
15710 scroll_has_scrolling = nk_true;
15711 }
15712 }
15713 } else if (!nk_panel_is_sub(layout->type)) {
15714 /* window mouse wheel scrolling */
15715 scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
15716 if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
15717 window->scrolled = nk_true;
15718 else window->scrolled = nk_false;
15719 } else scroll_has_scrolling = nk_false;
15720
15721 {
15722 /* vertical scrollbar */
15723 nk_flags state = 0;
15724 scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
15725 scroll.y = layout->bounds.y;
15726 scroll.w = scrollbar_size.x;
15727 scroll.h = layout->bounds.h;
15728
15729 scroll_offset = (float)*layout->offset_y;
15730 scroll_step = scroll.h * 0.10f;
15731 scroll_inc = scroll.h * 0.01f;
15732 scroll_target = (float)(int)(layout->at_y - scroll.y);
15733 scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
15734 scroll_offset, scroll_target, scroll_step, scroll_inc,
15735 &ctx->style.scrollv, in, style->font);
15736 *layout->offset_y = (nk_uint)scroll_offset;
15737 if (in && scroll_has_scrolling)
15738 in->mouse.scroll_delta.y = 0;
15739 }
15740 {
15741 /* horizontal scrollbar */
15742 nk_flags state = 0;
15743 scroll.x = layout->bounds.x;
15744 scroll.y = layout->bounds.y + layout->bounds.h;
15745 scroll.w = layout->bounds.w;
15746 scroll.h = scrollbar_size.y;
15747
15748 scroll_offset = (float)*layout->offset_x;
15749 scroll_target = (float)(int)(layout->max_x - scroll.x);
15750 scroll_step = layout->max_x * 0.05f;
15751 scroll_inc = layout->max_x * 0.005f;
15752 scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
15753 scroll_offset, scroll_target, scroll_step, scroll_inc,
15754 &ctx->style.scrollh, in, style->font);
15755 *layout->offset_x = (nk_uint)scroll_offset;
15756 }
15757 }
15758
15759 /* hide scroll if no user input */
15760 if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
15761 int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
15762 int is_window_hovered = nk_window_is_hovered(ctx);
15763 int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
15764 if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
15766 else window->scrollbar_hiding_timer = 0;
15767 } else window->scrollbar_hiding_timer = 0;
15768
15769 /* window border */
15770 if (layout->flags & NK_WINDOW_BORDER)
15771 {
15772 struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
15773 const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED)
15774 ? (style->window.border + window->bounds.y + layout->header_height)
15775 : ((layout->flags & NK_WINDOW_DYNAMIC)
15776 ? (layout->bounds.y + layout->bounds.h + layout->footer_height)
15777 : (window->bounds.y + window->bounds.h));
15778 struct nk_rect b = window->bounds;
15779 b.h = padding_y - window->bounds.y;
15780 nk_stroke_rect(out, b, 0, layout->border, border_color);
15781 }
15782
15783 /* scaler */
15784 if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
15785 {
15786 /* calculate scaler bounds */
15787 struct nk_rect scaler;
15788 scaler.w = scrollbar_size.x;
15789 scaler.h = scrollbar_size.y;
15790 scaler.y = layout->bounds.y + layout->bounds.h;
15791 if (layout->flags & NK_WINDOW_SCALE_LEFT)
15792 scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
15793 else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
15794 if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
15795 scaler.x -= scaler.w;
15796
15797 /* draw scaler */
15798 {const struct nk_style_item *item = &style->window.scaler;
15799 if (item->type == NK_STYLE_ITEM_IMAGE)
15800 nk_draw_image(out, scaler, &item->data.image, nk_white);
15801 else {
15802 if (layout->flags & NK_WINDOW_SCALE_LEFT) {
15803 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
15804 scaler.y + scaler.h, scaler.x + scaler.w,
15805 scaler.y + scaler.h, item->data.color);
15806 } else {
15807 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
15808 scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
15809 }
15810 }}
15811
15812 /* do window scaling */
15813 if (!(window->flags & NK_WINDOW_ROM)) {
15814 struct nk_vec2 window_size = style->window.min_size;
15815 int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
15816 int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
15817 NK_BUTTON_LEFT, scaler, nk_true);
15818
15819 if (left_mouse_down && left_mouse_click_in_scaler) {
15820 float delta_x = in->mouse.delta.x;
15821 if (layout->flags & NK_WINDOW_SCALE_LEFT) {
15822 delta_x = -delta_x;
15823 window->bounds.x += in->mouse.delta.x;
15824 }
15825 /* dragging in x-direction */
15826 if (window->bounds.w + delta_x >= window_size.x) {
15827 if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
15828 window->bounds.w = window->bounds.w + delta_x;
15829 scaler.x += in->mouse.delta.x;
15830 }
15831 }
15832 /* dragging in y-direction (only possible if static window) */
15833 if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
15834 if (window_size.y < window->bounds.h + in->mouse.delta.y) {
15835 if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
15836 window->bounds.h = window->bounds.h + in->mouse.delta.y;
15837 scaler.y += in->mouse.delta.y;
15838 }
15839 }
15840 }
15842 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
15843 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
15844 }
15845 }
15846 }
15847 if (!nk_panel_is_sub(layout->type)) {
15848 /* window is hidden so clear command buffer */
15849 if (layout->flags & NK_WINDOW_HIDDEN)
15850 nk_command_buffer_reset(&window->buffer);
15851 /* window is visible and not tab */
15852 else nk_finish(ctx, window);
15853 }
15854
15855 /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
15856 if (layout->flags & NK_WINDOW_REMOVE_ROM) {
15857 layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
15858 layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
15859 }
15860 window->flags = layout->flags;
15861
15862 /* property garbage collector */
15863 if (window->property.active && window->property.old != window->property.seq &&
15864 window->property.active == window->property.prev) {
15865 nk_zero(&window->property, sizeof(window->property));
15866 } else {
15867 window->property.old = window->property.seq;
15868 window->property.prev = window->property.active;
15869 window->property.seq = 0;
15870 }
15871 /* edit garbage collector */
15872 if (window->edit.active && window->edit.old != window->edit.seq &&
15873 window->edit.active == window->edit.prev) {
15874 nk_zero(&window->edit, sizeof(window->edit));
15875 } else {
15876 window->edit.old = window->edit.seq;
15877 window->edit.prev = window->edit.active;
15878 window->edit.seq = 0;
15879 }
15880 /* contextual garbage collector */
15881 if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
15882 window->popup.con_count = 0;
15883 window->popup.con_old = 0;
15884 window->popup.active_con = 0;
15885 } else {
15886 window->popup.con_old = window->popup.con_count;
15887 window->popup.con_count = 0;
15888 }
15889 window->popup.combo_count = 0;
15890 /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
15891 NK_ASSERT(!layout->row.tree_depth);
15892}
15893
15894
15895
15896
15897/* ===============================================================
15898 *
15899 * WINDOW
15900 *
15901 * ===============================================================*/
15902NK_LIB void*
15903nk_create_window(struct nk_context *ctx)
15904{
15905 struct nk_page_element *elem;
15906 elem = nk_create_page_element(ctx);
15907 if (!elem) return 0;
15908 elem->data.win.seq = ctx->seq;
15909 return &elem->data.win;
15910}
15911NK_LIB void
15912nk_free_window(struct nk_context *ctx, struct nk_window *win)
15913{
15914 /* unlink windows from list */
15915 struct nk_table *it = win->tables;
15916 if (win->popup.win) {
15917 nk_free_window(ctx, win->popup.win);
15918 win->popup.win = 0;
15919 }
15920 win->next = 0;
15921 win->prev = 0;
15922
15923 while (it) {
15924 /*free window state tables */
15925 struct nk_table *n = it->next;
15926 nk_remove_table(win, it);
15927 nk_free_table(ctx, it);
15928 if (it == win->tables)
15929 win->tables = n;
15930 it = n;
15931 }
15932
15933 /* link windows into freelist */
15934 {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
15935 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
15936 nk_free_page_element(ctx, pe);}
15937}
15938NK_LIB struct nk_window*
15939nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
15940{
15941 struct nk_window *iter;
15942 iter = ctx->begin;
15943 while (iter) {
15944 NK_ASSERT(iter != iter->next);
15945 if (iter->name == hash) {
15946 int max_len = nk_strlen(iter->name_string);
15947 if (!nk_stricmpn(iter->name_string, name, max_len))
15948 return iter;
15949 }
15950 iter = iter->next;
15951 }
15952 return 0;
15953}
15954NK_LIB void
15955nk_insert_window(struct nk_context *ctx, struct nk_window *win,
15956 enum nk_window_insert_location loc)
15957{
15958 const struct nk_window *iter;
15959 NK_ASSERT(ctx);
15960 NK_ASSERT(win);
15961 if (!win || !ctx) return;
15962
15963 iter = ctx->begin;
15964 while (iter) {
15965 NK_ASSERT(iter != iter->next);
15966 NK_ASSERT(iter != win);
15967 if (iter == win) return;
15968 iter = iter->next;
15969 }
15970
15971 if (!ctx->begin) {
15972 win->next = 0;
15973 win->prev = 0;
15974 ctx->begin = win;
15975 ctx->end = win;
15976 ctx->count = 1;
15977 return;
15978 }
15979 if (loc == NK_INSERT_BACK) {
15980 struct nk_window *end;
15981 end = ctx->end;
15982 end->flags |= NK_WINDOW_ROM;
15983 end->next = win;
15984 win->prev = ctx->end;
15985 win->next = 0;
15986 ctx->end = win;
15987 ctx->active = ctx->end;
15988 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
15989 } else {
15990 /*ctx->end->flags |= NK_WINDOW_ROM;*/
15991 ctx->begin->prev = win;
15992 win->next = ctx->begin;
15993 win->prev = 0;
15994 ctx->begin = win;
15995 ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
15996 }
15997 ctx->count++;
15998}
15999NK_LIB void
16000nk_remove_window(struct nk_context *ctx, struct nk_window *win)
16001{
16002 if (win == ctx->begin || win == ctx->end) {
16003 if (win == ctx->begin) {
16004 ctx->begin = win->next;
16005 if (win->next)
16006 win->next->prev = 0;
16007 }
16008 if (win == ctx->end) {
16009 ctx->end = win->prev;
16010 if (win->prev)
16011 win->prev->next = 0;
16012 }
16013 } else {
16014 if (win->next)
16015 win->next->prev = win->prev;
16016 if (win->prev)
16017 win->prev->next = win->next;
16018 }
16019 if (win == ctx->active || !ctx->active) {
16020 ctx->active = ctx->end;
16021 if (ctx->end)
16022 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
16023 }
16024 win->next = 0;
16025 win->prev = 0;
16026 ctx->count--;
16027}
16028NK_API int
16029nk_begin(struct nk_context *ctx, const char *title,
16030 struct nk_rect bounds, nk_flags flags)
16031{
16032 return nk_begin_titled(ctx, title, title, bounds, flags);
16033}
16034NK_API int
16035nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
16036 struct nk_rect bounds, nk_flags flags)
16037{
16038 struct nk_window *win;
16039 struct nk_style *style;
16040 nk_hash name_hash;
16041 int name_len;
16042 int ret = 0;
16043
16044 NK_ASSERT(ctx);
16045 NK_ASSERT(name);
16046 NK_ASSERT(title);
16047 NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
16048 NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
16049 if (!ctx || ctx->current || !title || !name)
16050 return 0;
16051
16052 /* find or create window */
16053 style = &ctx->style;
16054 name_len = (int)nk_strlen(name);
16055 name_hash = nk_murmur_hash(name, (int)name_len, NK_WINDOW_TITLE);
16056 win = nk_find_window(ctx, name_hash, name);
16057 if (!win) {
16058 /* create new window */
16059 nk_size name_length = (nk_size)name_len;
16060 win = (struct nk_window*)nk_create_window(ctx);
16061 NK_ASSERT(win);
16062 if (!win) return 0;
16063
16065 nk_insert_window(ctx, win, NK_INSERT_FRONT);
16066 else nk_insert_window(ctx, win, NK_INSERT_BACK);
16067 nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
16068
16069 win->flags = flags;
16070 win->bounds = bounds;
16071 win->name = name_hash;
16072 name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
16073 NK_MEMCPY(win->name_string, name, name_length);
16074 win->name_string[name_length] = 0;
16075 win->popup.win = 0;
16076 if (!ctx->active)
16077 ctx->active = win;
16078 } else {
16079 /* update window */
16080 win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
16081 win->flags |= flags;
16082 if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
16083 win->bounds = bounds;
16084 /* If this assert triggers you either:
16085 *
16086 * I.) Have more than one window with the same name or
16087 * II.) You forgot to actually draw the window.
16088 * More specific you did not call `nk_clear` (nk_clear will be
16089 * automatically called for you if you are using one of the
16090 * provided demo backends). */
16091 NK_ASSERT(win->seq != ctx->seq);
16092 win->seq = ctx->seq;
16093 if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
16094 ctx->active = win;
16095 ctx->end = win;
16096 }
16097 }
16098 if (win->flags & NK_WINDOW_HIDDEN) {
16099 ctx->current = win;
16100 win->layout = 0;
16101 return 0;
16102 } else nk_start(ctx, win);
16103
16104 /* window overlapping */
16105 if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
16106 {
16107 int inpanel, ishovered;
16108 struct nk_window *iter = win;
16109 float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
16110 (2.0f * style->window.header.label_padding.y);
16111 struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
16112 win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
16113
16114 /* activate window if hovered and no other window is overlapping this window */
16116 inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
16117 ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
16118 if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
16119 iter = win->next;
16120 while (iter) {
16121 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
16122 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
16123 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
16124 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
16125 (!(iter->flags & NK_WINDOW_HIDDEN)))
16126 break;
16127
16128 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
16129 NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
16130 iter->popup.win->bounds.x, iter->popup.win->bounds.y,
16131 iter->popup.win->bounds.w, iter->popup.win->bounds.h))
16132 break;
16133 iter = iter->next;
16134 }
16135 }
16136
16137 /* activate window if clicked */
16138 if (iter && inpanel && (win != ctx->end)) {
16139 iter = win->next;
16140 while (iter) {
16141 /* try to find a panel with higher priority in the same position */
16142 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
16143 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
16144 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
16145 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
16146 !(iter->flags & NK_WINDOW_HIDDEN))
16147 break;
16148 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
16149 NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
16150 iter->popup.win->bounds.x, iter->popup.win->bounds.y,
16151 iter->popup.win->bounds.w, iter->popup.win->bounds.h))
16152 break;
16153 iter = iter->next;
16154 }
16155 }
16156 if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
16157 win->flags |= (nk_flags)NK_WINDOW_ROM;
16158 iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
16159 ctx->active = iter;
16160 if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
16161 /* current window is active in that position so transfer to top
16162 * at the highest priority in stack */
16163 nk_remove_window(ctx, iter);
16164 nk_insert_window(ctx, iter, NK_INSERT_BACK);
16165 }
16166 } else {
16167 if (!iter && ctx->end != win) {
16168 if (!(win->flags & NK_WINDOW_BACKGROUND)) {
16169 /* current window is active in that position so transfer to top
16170 * at the highest priority in stack */
16171 nk_remove_window(ctx, win);
16172 nk_insert_window(ctx, win, NK_INSERT_BACK);
16173 }
16174 win->flags &= ~(nk_flags)NK_WINDOW_ROM;
16175 ctx->active = win;
16176 }
16177 if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
16178 win->flags |= NK_WINDOW_ROM;
16179 }
16180 }
16181 win->layout = (struct nk_panel*)nk_create_panel(ctx);
16182 ctx->current = win;
16183 ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
16184 win->layout->offset_x = &win->scrollbar.x;
16185 win->layout->offset_y = &win->scrollbar.y;
16186 return ret;
16187}
16188NK_API void
16189nk_end(struct nk_context *ctx)
16190{
16191 struct nk_panel *layout;
16192 NK_ASSERT(ctx);
16193 NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
16194 if (!ctx || !ctx->current)
16195 return;
16196
16197 layout = ctx->current->layout;
16198 if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
16199 ctx->current = 0;
16200 return;
16201 }
16202 nk_panel_end(ctx);
16203 nk_free_panel(ctx, ctx->current->layout);
16204 ctx->current = 0;
16205}
16206NK_API struct nk_rect
16207nk_window_get_bounds(const struct nk_context *ctx)
16208{
16209 NK_ASSERT(ctx);
16210 NK_ASSERT(ctx->current);
16211 if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
16212 return ctx->current->bounds;
16213}
16214NK_API struct nk_vec2
16215nk_window_get_position(const struct nk_context *ctx)
16216{
16217 NK_ASSERT(ctx);
16218 NK_ASSERT(ctx->current);
16219 if (!ctx || !ctx->current) return nk_vec2(0,0);
16220 return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
16221}
16222NK_API struct nk_vec2
16223nk_window_get_size(const struct nk_context *ctx)
16224{
16225 NK_ASSERT(ctx);
16226 NK_ASSERT(ctx->current);
16227 if (!ctx || !ctx->current) return nk_vec2(0,0);
16228 return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
16229}
16230NK_API float
16231nk_window_get_width(const struct nk_context *ctx)
16232{
16233 NK_ASSERT(ctx);
16234 NK_ASSERT(ctx->current);
16235 if (!ctx || !ctx->current) return 0;
16236 return ctx->current->bounds.w;
16237}
16238NK_API float
16239nk_window_get_height(const struct nk_context *ctx)
16240{
16241 NK_ASSERT(ctx);
16242 NK_ASSERT(ctx->current);
16243 if (!ctx || !ctx->current) return 0;
16244 return ctx->current->bounds.h;
16245}
16246NK_API struct nk_rect
16248{
16249 NK_ASSERT(ctx);
16250 NK_ASSERT(ctx->current);
16251 if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
16252 return ctx->current->layout->clip;
16253}
16254NK_API struct nk_vec2
16256{
16257 NK_ASSERT(ctx);
16258 NK_ASSERT(ctx->current);
16259 NK_ASSERT(ctx->current->layout);
16260 if (!ctx || !ctx->current) return nk_vec2(0,0);
16261 return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
16262}
16263NK_API struct nk_vec2
16265{
16266 NK_ASSERT(ctx);
16267 NK_ASSERT(ctx->current);
16268 NK_ASSERT(ctx->current->layout);
16269 if (!ctx || !ctx->current) return nk_vec2(0,0);
16270 return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
16271 ctx->current->layout->clip.y + ctx->current->layout->clip.h);
16272}
16273NK_API struct nk_vec2
16275{
16276 NK_ASSERT(ctx);
16277 NK_ASSERT(ctx->current);
16278 NK_ASSERT(ctx->current->layout);
16279 if (!ctx || !ctx->current) return nk_vec2(0,0);
16280 return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
16281}
16284{
16285 NK_ASSERT(ctx);
16286 NK_ASSERT(ctx->current);
16287 NK_ASSERT(ctx->current->layout);
16288 if (!ctx || !ctx->current) return 0;
16289 return &ctx->current->buffer;
16290}
16291NK_API struct nk_panel*
16293{
16294 NK_ASSERT(ctx);
16295 NK_ASSERT(ctx->current);
16296 if (!ctx || !ctx->current) return 0;
16297 return ctx->current->layout;
16298}
16299NK_API void
16301{
16302 struct nk_window *win;
16303 NK_ASSERT(ctx);
16304 NK_ASSERT(ctx->current);
16305 if (!ctx || !ctx->current)
16306 return ;
16307 win = ctx->current;
16308 if (offset_x)
16309 *offset_x = win->scrollbar.x;
16310 if (offset_y)
16311 *offset_y = win->scrollbar.y;
16312}
16313NK_API int
16314nk_window_has_focus(const struct nk_context *ctx)
16315{
16316 NK_ASSERT(ctx);
16317 NK_ASSERT(ctx->current);
16318 NK_ASSERT(ctx->current->layout);
16319 if (!ctx || !ctx->current) return 0;
16320 return ctx->current == ctx->active;
16321}
16322NK_API int
16324{
16325 NK_ASSERT(ctx);
16326 NK_ASSERT(ctx->current);
16327 if (!ctx || !ctx->current) return 0;
16328 if(ctx->current->flags & NK_WINDOW_HIDDEN)
16329 return 0;
16331}
16332NK_API int
16334{
16335 struct nk_window *iter;
16336 NK_ASSERT(ctx);
16337 if (!ctx) return 0;
16338 iter = ctx->begin;
16339 while (iter) {
16340 /* check if window is being hovered */
16341 if(!(iter->flags & NK_WINDOW_HIDDEN)) {
16342 /* check if window popup is being hovered */
16343 if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
16344 return 1;
16345
16346 if (iter->flags & NK_WINDOW_MINIMIZED) {
16347 struct nk_rect header = iter->bounds;
16348 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
16349 if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
16350 return 1;
16351 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
16352 return 1;
16353 }
16354 }
16355 iter = iter->next;
16356 }
16357 return 0;
16358}
16359NK_API int
16361{
16362 int any_hovered = nk_window_is_any_hovered(ctx);
16363 int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
16364 return any_hovered || any_active;
16365}
16366NK_API int
16367nk_window_is_collapsed(struct nk_context *ctx, const char *name)
16368{
16369 int title_len;
16370 nk_hash title_hash;
16371 struct nk_window *win;
16372 NK_ASSERT(ctx);
16373 if (!ctx) return 0;
16374
16375 title_len = (int)nk_strlen(name);
16376 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16377 win = nk_find_window(ctx, title_hash, name);
16378 if (!win) return 0;
16379 return win->flags & NK_WINDOW_MINIMIZED;
16380}
16381NK_API int
16382nk_window_is_closed(struct nk_context *ctx, const char *name)
16383{
16384 int title_len;
16385 nk_hash title_hash;
16386 struct nk_window *win;
16387 NK_ASSERT(ctx);
16388 if (!ctx) return 1;
16389
16390 title_len = (int)nk_strlen(name);
16391 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16392 win = nk_find_window(ctx, title_hash, name);
16393 if (!win) return 1;
16394 return (win->flags & NK_WINDOW_CLOSED);
16395}
16396NK_API int
16397nk_window_is_hidden(struct nk_context *ctx, const char *name)
16398{
16399 int title_len;
16400 nk_hash title_hash;
16401 struct nk_window *win;
16402 NK_ASSERT(ctx);
16403 if (!ctx) return 1;
16404
16405 title_len = (int)nk_strlen(name);
16406 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16407 win = nk_find_window(ctx, title_hash, name);
16408 if (!win) return 1;
16409 return (win->flags & NK_WINDOW_HIDDEN);
16410}
16411NK_API int
16412nk_window_is_active(struct nk_context *ctx, const char *name)
16413{
16414 int title_len;
16415 nk_hash title_hash;
16416 struct nk_window *win;
16417 NK_ASSERT(ctx);
16418 if (!ctx) return 0;
16419
16420 title_len = (int)nk_strlen(name);
16421 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16422 win = nk_find_window(ctx, title_hash, name);
16423 if (!win) return 0;
16424 return win == ctx->active;
16425}
16426NK_API struct nk_window*
16427nk_window_find(struct nk_context *ctx, const char *name)
16428{
16429 int title_len;
16430 nk_hash title_hash;
16431 title_len = (int)nk_strlen(name);
16432 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16433 return nk_find_window(ctx, title_hash, name);
16434}
16435NK_API void
16436nk_window_close(struct nk_context *ctx, const char *name)
16437{
16438 struct nk_window *win;
16439 NK_ASSERT(ctx);
16440 if (!ctx) return;
16441 win = nk_window_find(ctx, name);
16442 if (!win) return;
16443 NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
16444 if (ctx->current == win) return;
16445 win->flags |= NK_WINDOW_HIDDEN;
16446 win->flags |= NK_WINDOW_CLOSED;
16447}
16448NK_API void
16450 const char *name, struct nk_rect bounds)
16451{
16452 struct nk_window *win;
16453 NK_ASSERT(ctx);
16454 if (!ctx) return;
16455 win = nk_window_find(ctx, name);
16456 if (!win) return;
16457 NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window");
16458 win->bounds = bounds;
16459}
16460NK_API void
16462 const char *name, struct nk_vec2 pos)
16463{
16464 struct nk_window *win = nk_window_find(ctx, name);
16465 if (!win) return;
16466 win->bounds.x = pos.x;
16467 win->bounds.y = pos.y;
16468}
16469NK_API void
16470nk_window_set_size(struct nk_context *ctx,
16471 const char *name, struct nk_vec2 size)
16472{
16473 struct nk_window *win = nk_window_find(ctx, name);
16474 if (!win) return;
16475 win->bounds.w = size.x;
16476 win->bounds.h = size.y;
16477}
16478NK_API void
16479nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
16480{
16481 struct nk_window *win;
16482 NK_ASSERT(ctx);
16483 NK_ASSERT(ctx->current);
16484 if (!ctx || !ctx->current)
16485 return;
16486 win = ctx->current;
16487 win->scrollbar.x = offset_x;
16488 win->scrollbar.y = offset_y;
16489}
16490NK_API void
16491nk_window_collapse(struct nk_context *ctx, const char *name,
16492 enum nk_collapse_states c)
16493{
16494 int title_len;
16495 nk_hash title_hash;
16496 struct nk_window *win;
16497 NK_ASSERT(ctx);
16498 if (!ctx) return;
16499
16500 title_len = (int)nk_strlen(name);
16501 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16502 win = nk_find_window(ctx, title_hash, name);
16503 if (!win) return;
16504 if (c == NK_MINIMIZED)
16505 win->flags |= NK_WINDOW_MINIMIZED;
16506 else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
16507}
16508NK_API void
16509nk_window_collapse_if(struct nk_context *ctx, const char *name,
16510 enum nk_collapse_states c, int cond)
16511{
16512 NK_ASSERT(ctx);
16513 if (!ctx || !cond) return;
16514 nk_window_collapse(ctx, name, c);
16515}
16516NK_API void
16517nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
16518{
16519 int title_len;
16520 nk_hash title_hash;
16521 struct nk_window *win;
16522 NK_ASSERT(ctx);
16523 if (!ctx) return;
16524
16525 title_len = (int)nk_strlen(name);
16526 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16527 win = nk_find_window(ctx, title_hash, name);
16528 if (!win) return;
16529 if (s == NK_HIDDEN) {
16530 win->flags |= NK_WINDOW_HIDDEN;
16531 } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
16532}
16533NK_API void
16534nk_window_show_if(struct nk_context *ctx, const char *name,
16535 enum nk_show_states s, int cond)
16536{
16537 NK_ASSERT(ctx);
16538 if (!ctx || !cond) return;
16539 nk_window_show(ctx, name, s);
16540}
16541
16542NK_API void
16543nk_window_set_focus(struct nk_context *ctx, const char *name)
16544{
16545 int title_len;
16546 nk_hash title_hash;
16547 struct nk_window *win;
16548 NK_ASSERT(ctx);
16549 if (!ctx) return;
16550
16551 title_len = (int)nk_strlen(name);
16552 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16553 win = nk_find_window(ctx, title_hash, name);
16554 if (win && ctx->end != win) {
16555 nk_remove_window(ctx, win);
16556 nk_insert_window(ctx, win, NK_INSERT_BACK);
16557 }
16558 ctx->active = win;
16559}
16560
16561
16562
16563/* ===============================================================
16564 *
16565 * POPUP
16566 *
16567 * ===============================================================*/
16568NK_API int
16569nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
16570 const char *title, nk_flags flags, struct nk_rect rect)
16571{
16572 struct nk_window *popup;
16573 struct nk_window *win;
16574 struct nk_panel *panel;
16575
16576 int title_len;
16577 nk_hash title_hash;
16578 nk_size allocated;
16579
16580 NK_ASSERT(ctx);
16581 NK_ASSERT(title);
16582 NK_ASSERT(ctx->current);
16583 NK_ASSERT(ctx->current->layout);
16584 if (!ctx || !ctx->current || !ctx->current->layout)
16585 return 0;
16586
16587 win = ctx->current;
16588 panel = win->layout;
16589 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
16590 (void)panel;
16591 title_len = (int)nk_strlen(title);
16592 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
16593
16594 popup = win->popup.win;
16595 if (!popup) {
16596 popup = (struct nk_window*)nk_create_window(ctx);
16597 popup->parent = win;
16598 win->popup.win = popup;
16599 win->popup.active = 0;
16600 win->popup.type = NK_PANEL_POPUP;
16601 }
16602
16603 /* make sure we have correct popup */
16604 if (win->popup.name != title_hash) {
16605 if (!win->popup.active) {
16606 nk_zero(popup, sizeof(*popup));
16607 win->popup.name = title_hash;
16608 win->popup.active = 1;
16609 win->popup.type = NK_PANEL_POPUP;
16610 } else return 0;
16611 }
16612
16613 /* popup position is local to window */
16614 ctx->current = popup;
16615 rect.x += win->layout->clip.x;
16616 rect.y += win->layout->clip.y;
16617
16618 /* setup popup data */
16619 popup->parent = win;
16620 popup->bounds = rect;
16621 popup->seq = ctx->seq;
16622 popup->layout = (struct nk_panel*)nk_create_panel(ctx);
16623 popup->flags = flags;
16624 popup->flags |= NK_WINDOW_BORDER;
16625 if (type == NK_POPUP_DYNAMIC)
16626 popup->flags |= NK_WINDOW_DYNAMIC;
16627
16628 popup->buffer = win->buffer;
16629 nk_start_popup(ctx, win);
16630 allocated = ctx->memory.allocated;
16631 nk_push_scissor(&popup->buffer, nk_null_rect);
16632
16633 if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
16634 /* popup is running therefore invalidate parent panels */
16635 struct nk_panel *root;
16636 root = win->layout;
16637 while (root) {
16638 root->flags |= NK_WINDOW_ROM;
16640 root = root->parent;
16641 }
16642 win->popup.active = 1;
16643 popup->layout->offset_x = &popup->scrollbar.x;
16644 popup->layout->offset_y = &popup->scrollbar.y;
16645 popup->layout->parent = win->layout;
16646 return 1;
16647 } else {
16648 /* popup was closed/is invalid so cleanup */
16649 struct nk_panel *root;
16650 root = win->layout;
16651 while (root) {
16652 root->flags |= NK_WINDOW_REMOVE_ROM;
16653 root = root->parent;
16654 }
16655 win->popup.buf.active = 0;
16656 win->popup.active = 0;
16657 ctx->memory.allocated = allocated;
16658 ctx->current = win;
16659 nk_free_panel(ctx, popup->layout);
16660 popup->layout = 0;
16661 return 0;
16662 }
16663}
16664NK_LIB int
16665nk_nonblock_begin(struct nk_context *ctx,
16666 nk_flags flags, struct nk_rect body, struct nk_rect header,
16667 enum nk_panel_type panel_type)
16668{
16669 struct nk_window *popup;
16670 struct nk_window *win;
16671 struct nk_panel *panel;
16672 int is_active = nk_true;
16673
16674 NK_ASSERT(ctx);
16675 NK_ASSERT(ctx->current);
16676 NK_ASSERT(ctx->current->layout);
16677 if (!ctx || !ctx->current || !ctx->current->layout)
16678 return 0;
16679
16680 /* popups cannot have popups */
16681 win = ctx->current;
16682 panel = win->layout;
16683 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
16684 (void)panel;
16685 popup = win->popup.win;
16686 if (!popup) {
16687 /* create window for nonblocking popup */
16688 popup = (struct nk_window*)nk_create_window(ctx);
16689 popup->parent = win;
16690 win->popup.win = popup;
16691 win->popup.type = panel_type;
16692 nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
16693 } else {
16694 /* close the popup if user pressed outside or in the header */
16695 int pressed, in_body, in_header;
16696#ifdef NK_BUTTON_TRIGGER_ON_RELEASE
16698#else
16700#endif
16701 in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
16702 in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
16703 if (pressed && (!in_body || in_header))
16704 is_active = nk_false;
16705 }
16706 win->popup.header = header;
16707
16708 if (!is_active) {
16709 /* remove read only mode from all parent panels */
16710 struct nk_panel *root = win->layout;
16711 while (root) {
16712 root->flags |= NK_WINDOW_REMOVE_ROM;
16713 root = root->parent;
16714 }
16715 return is_active;
16716 }
16717 popup->bounds = body;
16718 popup->parent = win;
16719 popup->layout = (struct nk_panel*)nk_create_panel(ctx);
16720 popup->flags = flags;
16721 popup->flags |= NK_WINDOW_BORDER;
16722 popup->flags |= NK_WINDOW_DYNAMIC;
16723 popup->seq = ctx->seq;
16724 win->popup.active = 1;
16725 NK_ASSERT(popup->layout);
16726
16727 nk_start_popup(ctx, win);
16728 popup->buffer = win->buffer;
16729 nk_push_scissor(&popup->buffer, nk_null_rect);
16730 ctx->current = popup;
16731
16732 nk_panel_begin(ctx, 0, panel_type);
16733 win->buffer = popup->buffer;
16734 popup->layout->parent = win->layout;
16735 popup->layout->offset_x = &popup->scrollbar.x;
16736 popup->layout->offset_y = &popup->scrollbar.y;
16737
16738 /* set read only mode to all parent panels */
16739 {struct nk_panel *root;
16740 root = win->layout;
16741 while (root) {
16742 root->flags |= NK_WINDOW_ROM;
16743 root = root->parent;
16744 }}
16745 return is_active;
16746}
16747NK_API void
16748nk_popup_close(struct nk_context *ctx)
16749{
16750 struct nk_window *popup;
16751 NK_ASSERT(ctx);
16752 if (!ctx || !ctx->current) return;
16753
16754 popup = ctx->current;
16755 NK_ASSERT(popup->parent);
16756 NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
16757 popup->flags |= NK_WINDOW_HIDDEN;
16758}
16759NK_API void
16760nk_popup_end(struct nk_context *ctx)
16761{
16762 struct nk_window *win;
16763 struct nk_window *popup;
16764
16765 NK_ASSERT(ctx);
16766 NK_ASSERT(ctx->current);
16767 NK_ASSERT(ctx->current->layout);
16768 if (!ctx || !ctx->current || !ctx->current->layout)
16769 return;
16770
16771 popup = ctx->current;
16772 if (!popup->parent) return;
16773 win = popup->parent;
16774 if (popup->flags & NK_WINDOW_HIDDEN) {
16775 struct nk_panel *root;
16776 root = win->layout;
16777 while (root) {
16778 root->flags |= NK_WINDOW_REMOVE_ROM;
16779 root = root->parent;
16780 }
16781 win->popup.active = 0;
16782 }
16783 nk_push_scissor(&popup->buffer, nk_null_rect);
16784 nk_end(ctx);
16785
16786 win->buffer = popup->buffer;
16787 nk_finish_popup(ctx, win);
16788 ctx->current = win;
16789 nk_push_scissor(&win->buffer, win->layout->clip);
16790}
16791NK_API void
16793{
16794 struct nk_window *popup;
16795
16796 NK_ASSERT(ctx);
16797 NK_ASSERT(ctx->current);
16798 NK_ASSERT(ctx->current->layout);
16799 if (!ctx || !ctx->current || !ctx->current->layout)
16800 return;
16801
16802 popup = ctx->current;
16803 if (offset_x)
16804 *offset_x = popup->scrollbar.x;
16805 if (offset_y)
16806 *offset_y = popup->scrollbar.y;
16807}
16808NK_API void
16809nk_popup_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
16810{
16811 struct nk_window *popup;
16812
16813 NK_ASSERT(ctx);
16814 NK_ASSERT(ctx->current);
16815 NK_ASSERT(ctx->current->layout);
16816 if (!ctx || !ctx->current || !ctx->current->layout)
16817 return;
16818
16819 popup = ctx->current;
16820 popup->scrollbar.x = offset_x;
16821 popup->scrollbar.y = offset_y;
16822}
16823
16824
16825
16826/* ==============================================================
16827 *
16828 * CONTEXTUAL
16829 *
16830 * ===============================================================*/
16831NK_API int
16832nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
16833 struct nk_rect trigger_bounds)
16834{
16835 struct nk_window *win;
16836 struct nk_window *popup;
16837 struct nk_rect body;
16838
16839 NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0};
16840 int is_clicked = 0;
16841 int is_open = 0;
16842 int ret = 0;
16843
16844 NK_ASSERT(ctx);
16845 NK_ASSERT(ctx->current);
16846 NK_ASSERT(ctx->current->layout);
16847 if (!ctx || !ctx->current || !ctx->current->layout)
16848 return 0;
16849
16850 win = ctx->current;
16851 ++win->popup.con_count;
16852 if (ctx->current != ctx->active)
16853 return 0;
16854
16855 /* check if currently active contextual is active */
16856 popup = win->popup.win;
16857 is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
16858 is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
16859 if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
16860 return 0;
16861 if (!is_open && win->popup.active_con)
16862 win->popup.active_con = 0;
16863 if ((!is_open && !is_clicked))
16864 return 0;
16865
16866 /* calculate contextual position on click */
16867 win->popup.active_con = win->popup.con_count;
16868 if (is_clicked) {
16869 body.x = ctx->input.mouse.pos.x;
16870 body.y = ctx->input.mouse.pos.y;
16871 } else {
16872 body.x = popup->bounds.x;
16873 body.y = popup->bounds.y;
16874 }
16875 body.w = size.x;
16876 body.h = size.y;
16877
16878 /* start nonblocking contextual popup */
16879 ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
16880 null_rect, NK_PANEL_CONTEXTUAL);
16881 if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
16882 else {
16883 win->popup.active_con = 0;
16884 win->popup.type = NK_PANEL_NONE;
16885 if (win->popup.win)
16886 win->popup.win->flags = 0;
16887 }
16888 return ret;
16889}
16890NK_API int
16891nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
16892 nk_flags alignment)
16893{
16894 struct nk_window *win;
16895 const struct nk_input *in;
16896 const struct nk_style *style;
16897
16898 struct nk_rect bounds;
16899 enum nk_widget_layout_states state;
16900
16901 NK_ASSERT(ctx);
16902 NK_ASSERT(ctx->current);
16903 NK_ASSERT(ctx->current->layout);
16904 if (!ctx || !ctx->current || !ctx->current->layout)
16905 return 0;
16906
16907 win = ctx->current;
16908 style = &ctx->style;
16909 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
16910 if (!state) return nk_false;
16911
16912 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
16913 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
16914 text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
16916 return nk_true;
16917 }
16918 return nk_false;
16919}
16920NK_API int
16921nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
16922{
16923 return nk_contextual_item_text(ctx, label, nk_strlen(label), align);
16924}
16925NK_API int
16926nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
16927 const char *text, int len, nk_flags align)
16928{
16929 struct nk_window *win;
16930 const struct nk_input *in;
16931 const struct nk_style *style;
16932
16933 struct nk_rect bounds;
16934 enum nk_widget_layout_states state;
16935
16936 NK_ASSERT(ctx);
16937 NK_ASSERT(ctx->current);
16938 NK_ASSERT(ctx->current->layout);
16939 if (!ctx || !ctx->current || !ctx->current->layout)
16940 return 0;
16941
16942 win = ctx->current;
16943 style = &ctx->style;
16944 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
16945 if (!state) return nk_false;
16946
16947 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
16948 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
16949 img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
16951 return nk_true;
16952 }
16953 return nk_false;
16954}
16955NK_API int
16956nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
16957 const char *label, nk_flags align)
16958{
16959 return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);
16960}
16961NK_API int
16963 const char *text, int len, nk_flags align)
16964{
16965 struct nk_window *win;
16966 const struct nk_input *in;
16967 const struct nk_style *style;
16968
16969 struct nk_rect bounds;
16970 enum nk_widget_layout_states state;
16971
16972 NK_ASSERT(ctx);
16973 NK_ASSERT(ctx->current);
16974 NK_ASSERT(ctx->current->layout);
16975 if (!ctx || !ctx->current || !ctx->current->layout)
16976 return 0;
16977
16978 win = ctx->current;
16979 style = &ctx->style;
16980 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
16981 if (!state) return nk_false;
16982
16983 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
16984 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
16985 symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
16987 return nk_true;
16988 }
16989 return nk_false;
16990}
16991NK_API int
16993 const char *text, nk_flags align)
16994{
16995 return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);
16996}
16997NK_API void
16999{
17000 NK_ASSERT(ctx);
17001 NK_ASSERT(ctx->current);
17002 NK_ASSERT(ctx->current->layout);
17003 if (!ctx || !ctx->current || !ctx->current->layout) return;
17004 nk_popup_close(ctx);
17005}
17006NK_API void
17007nk_contextual_end(struct nk_context *ctx)
17008{
17009 struct nk_window *popup;
17010 struct nk_panel *panel;
17011 NK_ASSERT(ctx);
17012 NK_ASSERT(ctx->current);
17013 if (!ctx || !ctx->current) return;
17014
17015 popup = ctx->current;
17016 panel = popup->layout;
17017 NK_ASSERT(popup->parent);
17018 NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
17019 if (panel->flags & NK_WINDOW_DYNAMIC) {
17020 /* Close behavior
17021 This is a bit of a hack solution since we do not know before we end our popup
17022 how big it will be. We therefore do not directly know when a
17023 click outside the non-blocking popup must close it at that direct frame.
17024 Instead it will be closed in the next frame.*/
17025 struct nk_rect body = {0,0,0,0};
17026 if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
17027 struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
17028 body = panel->bounds;
17029 body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
17030 body.h = (panel->bounds.y + panel->bounds.h) - body.y;
17031 }
17032 {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
17033 int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
17034 if (pressed && in_body)
17035 popup->flags |= NK_WINDOW_HIDDEN;
17036 }
17037 }
17038 if (popup->flags & NK_WINDOW_HIDDEN)
17039 popup->seq = 0;
17040 nk_popup_end(ctx);
17041 return;
17042}
17043
17044
17045
17046
17047/* ===============================================================
17048 *
17049 * MENU
17050 *
17051 * ===============================================================*/
17052NK_API void
17053nk_menubar_begin(struct nk_context *ctx)
17054{
17055 struct nk_panel *layout;
17056 NK_ASSERT(ctx);
17057 NK_ASSERT(ctx->current);
17058 NK_ASSERT(ctx->current->layout);
17059 if (!ctx || !ctx->current || !ctx->current->layout)
17060 return;
17061
17062 layout = ctx->current->layout;
17063 NK_ASSERT(layout->at_y == layout->bounds.y);
17064 /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
17065 If you want a menubar the first nuklear function after `nk_begin` has to be a
17066 `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
17067 widgets (also supports multiple rows).
17068 Example:
17069 if (nk_begin(...)) {
17070 nk_menubar_begin(...);
17071 nk_layout_xxxx(...);
17072 nk_button(...);
17073 nk_layout_xxxx(...);
17074 nk_button(...);
17075 nk_menubar_end(...);
17076 }
17077 nk_end(...);
17078 */
17079 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
17080 return;
17081
17082 layout->menu.x = layout->at_x;
17083 layout->menu.y = layout->at_y + layout->row.height;
17084 layout->menu.w = layout->bounds.w;
17085 layout->menu.offset.x = *layout->offset_x;
17086 layout->menu.offset.y = *layout->offset_y;
17087 *layout->offset_y = 0;
17088}
17089NK_API void
17090nk_menubar_end(struct nk_context *ctx)
17091{
17092 struct nk_window *win;
17093 struct nk_panel *layout;
17094 struct nk_command_buffer *out;
17095
17096 NK_ASSERT(ctx);
17097 NK_ASSERT(ctx->current);
17098 NK_ASSERT(ctx->current->layout);
17099 if (!ctx || !ctx->current || !ctx->current->layout)
17100 return;
17101
17102 win = ctx->current;
17103 out = &win->buffer;
17104 layout = win->layout;
17105 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
17106 return;
17107
17108 layout->menu.h = layout->at_y - layout->menu.y;
17109 layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
17110 layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
17111
17112 *layout->offset_x = layout->menu.offset.x;
17113 *layout->offset_y = layout->menu.offset.y;
17114 layout->at_y = layout->bounds.y - layout->row.height;
17115
17116 layout->clip.y = layout->bounds.y;
17117 layout->clip.h = layout->bounds.h;
17118 nk_push_scissor(out, layout->clip);
17119}
17120NK_INTERN int
17121nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
17122 const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
17123{
17124 int is_open = 0;
17125 int is_active = 0;
17126 struct nk_rect body;
17127 struct nk_window *popup;
17128 nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
17129
17130 NK_ASSERT(ctx);
17131 NK_ASSERT(ctx->current);
17132 NK_ASSERT(ctx->current->layout);
17133 if (!ctx || !ctx->current || !ctx->current->layout)
17134 return 0;
17135
17136 body.x = header.x;
17137 body.w = size.x;
17138 body.y = header.y + header.h;
17139 body.h = size.y;
17140
17141 popup = win->popup.win;
17142 is_open = popup ? nk_true : nk_false;
17143 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
17144 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
17145 (!is_open && !is_active && !is_clicked)) return 0;
17146 if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
17147 return 0;
17148
17149 win->popup.type = NK_PANEL_MENU;
17150 win->popup.name = hash;
17151 return 1;
17152}
17153NK_API int
17154nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
17155 nk_flags align, struct nk_vec2 size)
17156{
17157 struct nk_window *win;
17158 const struct nk_input *in;
17159 struct nk_rect header;
17160 int is_clicked = nk_false;
17161 nk_flags state;
17162
17163 NK_ASSERT(ctx);
17164 NK_ASSERT(ctx->current);
17165 NK_ASSERT(ctx->current->layout);
17166 if (!ctx || !ctx->current || !ctx->current->layout)
17167 return 0;
17168
17169 win = ctx->current;
17170 state = nk_widget(&header, ctx);
17171 if (!state) return 0;
17172 in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17173 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
17174 title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
17175 is_clicked = nk_true;
17176 return nk_menu_begin(ctx, win, title, is_clicked, header, size);
17177}
17178NK_API int nk_menu_begin_label(struct nk_context *ctx,
17179 const char *text, nk_flags align, struct nk_vec2 size)
17180{
17181 return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);
17182}
17183NK_API int
17184nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
17185 struct nk_vec2 size)
17186{
17187 struct nk_window *win;
17188 struct nk_rect header;
17189 const struct nk_input *in;
17190 int is_clicked = nk_false;
17191 nk_flags state;
17192
17193 NK_ASSERT(ctx);
17194 NK_ASSERT(ctx->current);
17195 NK_ASSERT(ctx->current->layout);
17196 if (!ctx || !ctx->current || !ctx->current->layout)
17197 return 0;
17198
17199 win = ctx->current;
17200 state = nk_widget(&header, ctx);
17201 if (!state) return 0;
17202 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17203 if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
17204 img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
17205 is_clicked = nk_true;
17206 return nk_menu_begin(ctx, win, id, is_clicked, header, size);
17207}
17208NK_API int
17209nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
17210 enum nk_symbol_type sym, struct nk_vec2 size)
17211{
17212 struct nk_window *win;
17213 const struct nk_input *in;
17214 struct nk_rect header;
17215 int is_clicked = nk_false;
17216 nk_flags state;
17217
17218 NK_ASSERT(ctx);
17219 NK_ASSERT(ctx->current);
17220 NK_ASSERT(ctx->current->layout);
17221 if (!ctx || !ctx->current || !ctx->current->layout)
17222 return 0;
17223
17224 win = ctx->current;
17225 state = nk_widget(&header, ctx);
17226 if (!state) return 0;
17227 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17228 if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header,
17229 sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
17230 is_clicked = nk_true;
17231 return nk_menu_begin(ctx, win, id, is_clicked, header, size);
17232}
17233NK_API int
17234nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
17235 nk_flags align, struct nk_image img, struct nk_vec2 size)
17236{
17237 struct nk_window *win;
17238 struct nk_rect header;
17239 const struct nk_input *in;
17240 int is_clicked = nk_false;
17241 nk_flags state;
17242
17243 NK_ASSERT(ctx);
17244 NK_ASSERT(ctx->current);
17245 NK_ASSERT(ctx->current->layout);
17246 if (!ctx || !ctx->current || !ctx->current->layout)
17247 return 0;
17248
17249 win = ctx->current;
17250 state = nk_widget(&header, ctx);
17251 if (!state) return 0;
17252 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17253 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
17254 header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
17255 ctx->style.font, in))
17256 is_clicked = nk_true;
17257 return nk_menu_begin(ctx, win, title, is_clicked, header, size);
17258}
17259NK_API int
17261 const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
17262{
17263 return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);
17264}
17265NK_API int
17266nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
17267 nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
17268{
17269 struct nk_window *win;
17270 struct nk_rect header;
17271 const struct nk_input *in;
17272 int is_clicked = nk_false;
17273 nk_flags state;
17274
17275 NK_ASSERT(ctx);
17276 NK_ASSERT(ctx->current);
17277 NK_ASSERT(ctx->current->layout);
17278 if (!ctx || !ctx->current || !ctx->current->layout)
17279 return 0;
17280
17281 win = ctx->current;
17282 state = nk_widget(&header, ctx);
17283 if (!state) return 0;
17284
17285 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17286 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
17287 header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
17288 ctx->style.font, in)) is_clicked = nk_true;
17289 return nk_menu_begin(ctx, win, title, is_clicked, header, size);
17290}
17291NK_API int
17293 const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
17294{
17295 return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);
17296}
17297NK_API int
17298nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
17299{
17300 return nk_contextual_item_text(ctx, title, len, align);
17301}
17302NK_API int
17303nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
17304{
17305 return nk_contextual_item_label(ctx, label, align);
17306}
17307NK_API int
17308nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
17309 const char *label, nk_flags align)
17310{
17311 return nk_contextual_item_image_label(ctx, img, label, align);
17312}
17313NK_API int
17314nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
17315 const char *text, int len, nk_flags align)
17316{
17317 return nk_contextual_item_image_text(ctx, img, text, len, align);
17318}
17320 const char *text, int len, nk_flags align)
17321{
17322 return nk_contextual_item_symbol_text(ctx, sym, text, len, align);
17323}
17325 const char *label, nk_flags align)
17326{
17327 return nk_contextual_item_symbol_label(ctx, sym, label, align);
17328}
17329NK_API void nk_menu_close(struct nk_context *ctx)
17330{
17332}
17333NK_API void
17334nk_menu_end(struct nk_context *ctx)
17335{
17336 nk_contextual_end(ctx);
17337}
17338
17339
17340
17341
17342/* ===============================================================
17343 *
17344 * LAYOUT
17345 *
17346 * ===============================================================*/
17347NK_API void
17348nk_layout_set_min_row_height(struct nk_context *ctx, float height)
17349{
17350 struct nk_window *win;
17351 struct nk_panel *layout;
17352
17353 NK_ASSERT(ctx);
17354 NK_ASSERT(ctx->current);
17355 NK_ASSERT(ctx->current->layout);
17356 if (!ctx || !ctx->current || !ctx->current->layout)
17357 return;
17358
17359 win = ctx->current;
17360 layout = win->layout;
17361 layout->row.min_height = height;
17362}
17363NK_API void
17365{
17366 struct nk_window *win;
17367 struct nk_panel *layout;
17368
17369 NK_ASSERT(ctx);
17370 NK_ASSERT(ctx->current);
17371 NK_ASSERT(ctx->current->layout);
17372 if (!ctx || !ctx->current || !ctx->current->layout)
17373 return;
17374
17375 win = ctx->current;
17376 layout = win->layout;
17377 layout->row.min_height = ctx->style.font->height;
17378 layout->row.min_height += ctx->style.text.padding.y*2;
17380}
17381NK_LIB float
17382nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
17383 float total_space, int columns)
17384{
17385 float panel_padding;
17386 float panel_spacing;
17387 float panel_space;
17388
17389 struct nk_vec2 spacing;
17390 struct nk_vec2 padding;
17391
17392 spacing = style->window.spacing;
17393 padding = nk_panel_get_padding(style, type);
17394
17395 /* calculate the usable panel space */
17396 panel_padding = 2 * padding.x;
17397 panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
17398 panel_space = total_space - panel_padding - panel_spacing;
17399 return panel_space;
17400}
17401NK_LIB void
17402nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
17403 float height, int cols)
17404{
17405 struct nk_panel *layout;
17406 const struct nk_style *style;
17407 struct nk_command_buffer *out;
17408
17409 struct nk_vec2 item_spacing;
17410 struct nk_color color;
17411
17412 NK_ASSERT(ctx);
17413 NK_ASSERT(ctx->current);
17414 NK_ASSERT(ctx->current->layout);
17415 if (!ctx || !ctx->current || !ctx->current->layout)
17416 return;
17417
17418 /* prefetch some configuration data */
17419 layout = win->layout;
17420 style = &ctx->style;
17421 out = &win->buffer;
17422 color = style->window.background;
17423 item_spacing = style->window.spacing;
17424
17425 /* if one of these triggers you forgot to add an `if` condition around either
17426 a window, group, popup, combobox or contextual menu `begin` and `end` block.
17427 Example:
17428 if (nk_begin(...) {...} nk_end(...); or
17429 if (nk_group_begin(...) { nk_group_end(...);} */
17430 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
17431 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
17432 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
17433
17434 /* update the current row and set the current row layout */
17435 layout->row.index = 0;
17436 layout->at_y += layout->row.height;
17437 layout->row.columns = cols;
17438 if (height == 0.0f)
17439 layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
17440 else layout->row.height = height + item_spacing.y;
17441
17442 layout->row.item_offset = 0;
17443 if (layout->flags & NK_WINDOW_DYNAMIC) {
17444 /* draw background for dynamic panels */
17445 struct nk_rect background;
17446 background.x = win->bounds.x;
17447 background.w = win->bounds.w;
17448 background.y = layout->at_y - 1.0f;
17449 background.h = layout->row.height + 1.0f;
17450 nk_fill_rect(out, background, 0, color);
17451 }
17452}
17453NK_LIB void
17454nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
17455 float height, int cols, int width)
17456{
17457 /* update the current row and set the current row layout */
17458 struct nk_window *win;
17459 NK_ASSERT(ctx);
17460 NK_ASSERT(ctx->current);
17461 NK_ASSERT(ctx->current->layout);
17462 if (!ctx || !ctx->current || !ctx->current->layout)
17463 return;
17464
17465 win = ctx->current;
17466 nk_panel_layout(ctx, win, height, cols);
17467 if (fmt == NK_DYNAMIC)
17470
17471 win->layout->row.ratio = 0;
17472 win->layout->row.filled = 0;
17473 win->layout->row.item_offset = 0;
17474 win->layout->row.item_width = (float)width;
17475}
17476NK_API float
17477nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
17478{
17479 struct nk_window *win;
17480 NK_ASSERT(ctx);
17481 NK_ASSERT(pixel_width);
17482 if (!ctx || !ctx->current || !ctx->current->layout) return 0;
17483 win = ctx->current;
17484 return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
17485}
17486NK_API void
17487nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
17488{
17489 nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
17490}
17491NK_API void
17492nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
17493{
17494 nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
17495}
17496NK_API void
17497nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
17498 float row_height, int cols)
17499{
17500 struct nk_window *win;
17501 struct nk_panel *layout;
17502
17503 NK_ASSERT(ctx);
17504 NK_ASSERT(ctx->current);
17505 NK_ASSERT(ctx->current->layout);
17506 if (!ctx || !ctx->current || !ctx->current->layout)
17507 return;
17508
17509 win = ctx->current;
17510 layout = win->layout;
17511 nk_panel_layout(ctx, win, row_height, cols);
17512 if (fmt == NK_DYNAMIC)
17513 layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
17514 else layout->row.type = NK_LAYOUT_STATIC_ROW;
17515
17516 layout->row.ratio = 0;
17517 layout->row.filled = 0;
17518 layout->row.item_width = 0;
17519 layout->row.item_offset = 0;
17520 layout->row.columns = cols;
17521}
17522NK_API void
17523nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
17524{
17525 struct nk_window *win;
17526 struct nk_panel *layout;
17527
17528 NK_ASSERT(ctx);
17529 NK_ASSERT(ctx->current);
17530 NK_ASSERT(ctx->current->layout);
17531 if (!ctx || !ctx->current || !ctx->current->layout)
17532 return;
17533
17534 win = ctx->current;
17535 layout = win->layout;
17536 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
17537 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
17538 return;
17539
17540 if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
17541 float ratio = ratio_or_width;
17542 if ((ratio + layout->row.filled) > 1.0f) return;
17543 if (ratio > 0.0f)
17544 layout->row.item_width = NK_SATURATE(ratio);
17545 else layout->row.item_width = 1.0f - layout->row.filled;
17546 } else layout->row.item_width = ratio_or_width;
17547}
17548NK_API void
17549nk_layout_row_end(struct nk_context *ctx)
17550{
17551 struct nk_window *win;
17552 struct nk_panel *layout;
17553
17554 NK_ASSERT(ctx);
17555 NK_ASSERT(ctx->current);
17556 NK_ASSERT(ctx->current->layout);
17557 if (!ctx || !ctx->current || !ctx->current->layout)
17558 return;
17559
17560 win = ctx->current;
17561 layout = win->layout;
17562 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
17563 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
17564 return;
17565 layout->row.item_width = 0;
17566 layout->row.item_offset = 0;
17567}
17568NK_API void
17569nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
17570 float height, int cols, const float *ratio)
17571{
17572 int i;
17573 int n_undef = 0;
17574 struct nk_window *win;
17575 struct nk_panel *layout;
17576
17577 NK_ASSERT(ctx);
17578 NK_ASSERT(ctx->current);
17579 NK_ASSERT(ctx->current->layout);
17580 if (!ctx || !ctx->current || !ctx->current->layout)
17581 return;
17582
17583 win = ctx->current;
17584 layout = win->layout;
17585 nk_panel_layout(ctx, win, height, cols);
17586 if (fmt == NK_DYNAMIC) {
17587 /* calculate width of undefined widget ratios */
17588 float r = 0;
17589 layout->row.ratio = ratio;
17590 for (i = 0; i < cols; ++i) {
17591 if (ratio[i] < 0.0f)
17592 n_undef++;
17593 else r += ratio[i];
17594 }
17595 r = NK_SATURATE(1.0f - r);
17596 layout->row.type = NK_LAYOUT_DYNAMIC;
17597 layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
17598 } else {
17599 layout->row.ratio = ratio;
17600 layout->row.type = NK_LAYOUT_STATIC;
17601 layout->row.item_width = 0;
17602 layout->row.item_offset = 0;
17603 }
17604 layout->row.item_offset = 0;
17605 layout->row.filled = 0;
17606}
17607NK_API void
17608nk_layout_row_template_begin(struct nk_context *ctx, float height)
17609{
17610 struct nk_window *win;
17611 struct nk_panel *layout;
17612
17613 NK_ASSERT(ctx);
17614 NK_ASSERT(ctx->current);
17615 NK_ASSERT(ctx->current->layout);
17616 if (!ctx || !ctx->current || !ctx->current->layout)
17617 return;
17618
17619 win = ctx->current;
17620 layout = win->layout;
17621 nk_panel_layout(ctx, win, height, 1);
17622 layout->row.type = NK_LAYOUT_TEMPLATE;
17623 layout->row.columns = 0;
17624 layout->row.ratio = 0;
17625 layout->row.item_width = 0;
17626 layout->row.item_height = 0;
17627 layout->row.item_offset = 0;
17628 layout->row.filled = 0;
17629 layout->row.item.x = 0;
17630 layout->row.item.y = 0;
17631 layout->row.item.w = 0;
17632 layout->row.item.h = 0;
17633}
17634NK_API void
17636{
17637 struct nk_window *win;
17638 struct nk_panel *layout;
17639
17640 NK_ASSERT(ctx);
17641 NK_ASSERT(ctx->current);
17642 NK_ASSERT(ctx->current->layout);
17643 if (!ctx || !ctx->current || !ctx->current->layout)
17644 return;
17645
17646 win = ctx->current;
17647 layout = win->layout;
17648 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17649 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
17650 if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17651 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
17652 layout->row.templates[layout->row.columns++] = -1.0f;
17653}
17654NK_API void
17655nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
17656{
17657 struct nk_window *win;
17658 struct nk_panel *layout;
17659
17660 NK_ASSERT(ctx);
17661 NK_ASSERT(ctx->current);
17662 NK_ASSERT(ctx->current->layout);
17663 if (!ctx || !ctx->current || !ctx->current->layout)
17664 return;
17665
17666 win = ctx->current;
17667 layout = win->layout;
17668 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17669 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
17670 if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17671 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
17672 layout->row.templates[layout->row.columns++] = -min_width;
17673}
17674NK_API void
17675nk_layout_row_template_push_static(struct nk_context *ctx, float width)
17676{
17677 struct nk_window *win;
17678 struct nk_panel *layout;
17679
17680 NK_ASSERT(ctx);
17681 NK_ASSERT(ctx->current);
17682 NK_ASSERT(ctx->current->layout);
17683 if (!ctx || !ctx->current || !ctx->current->layout)
17684 return;
17685
17686 win = ctx->current;
17687 layout = win->layout;
17688 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17689 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
17690 if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17691 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
17692 layout->row.templates[layout->row.columns++] = width;
17693}
17694NK_API void
17696{
17697 struct nk_window *win;
17698 struct nk_panel *layout;
17699
17700 int i = 0;
17701 int variable_count = 0;
17702 int min_variable_count = 0;
17703 float min_fixed_width = 0.0f;
17704 float total_fixed_width = 0.0f;
17705 float max_variable_width = 0.0f;
17706
17707 NK_ASSERT(ctx);
17708 NK_ASSERT(ctx->current);
17709 NK_ASSERT(ctx->current->layout);
17710 if (!ctx || !ctx->current || !ctx->current->layout)
17711 return;
17712
17713 win = ctx->current;
17714 layout = win->layout;
17715 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17716 if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17717 for (i = 0; i < layout->row.columns; ++i) {
17718 float width = layout->row.templates[i];
17719 if (width >= 0.0f) {
17720 total_fixed_width += width;
17721 min_fixed_width += width;
17722 } else if (width < -1.0f) {
17723 width = -width;
17724 total_fixed_width += width;
17725 max_variable_width = NK_MAX(max_variable_width, width);
17726 variable_count++;
17727 } else {
17728 min_variable_count++;
17729 variable_count++;
17730 }
17731 }
17732 if (variable_count) {
17733 float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
17734 layout->bounds.w, layout->row.columns);
17735 float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
17736 int enough_space = var_width >= max_variable_width;
17737 if (!enough_space)
17738 var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
17739 for (i = 0; i < layout->row.columns; ++i) {
17740 float *width = &layout->row.templates[i];
17741 *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
17742 }
17743 }
17744}
17745NK_API void
17747 float height, int widget_count)
17748{
17749 struct nk_window *win;
17750 struct nk_panel *layout;
17751
17752 NK_ASSERT(ctx);
17753 NK_ASSERT(ctx->current);
17754 NK_ASSERT(ctx->current->layout);
17755 if (!ctx || !ctx->current || !ctx->current->layout)
17756 return;
17757
17758 win = ctx->current;
17759 layout = win->layout;
17760 nk_panel_layout(ctx, win, height, widget_count);
17761 if (fmt == NK_STATIC)
17762 layout->row.type = NK_LAYOUT_STATIC_FREE;
17763 else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
17764
17765 layout->row.ratio = 0;
17766 layout->row.filled = 0;
17767 layout->row.item_width = 0;
17768 layout->row.item_offset = 0;
17769}
17770NK_API void
17772{
17773 struct nk_window *win;
17774 struct nk_panel *layout;
17775
17776 NK_ASSERT(ctx);
17777 NK_ASSERT(ctx->current);
17778 NK_ASSERT(ctx->current->layout);
17779 if (!ctx || !ctx->current || !ctx->current->layout)
17780 return;
17781
17782 win = ctx->current;
17783 layout = win->layout;
17784 layout->row.item_width = 0;
17785 layout->row.item_height = 0;
17786 layout->row.item_offset = 0;
17787 nk_zero(&layout->row.item, sizeof(layout->row.item));
17788}
17789NK_API void
17790nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
17791{
17792 struct nk_window *win;
17793 struct nk_panel *layout;
17794
17795 NK_ASSERT(ctx);
17796 NK_ASSERT(ctx->current);
17797 NK_ASSERT(ctx->current->layout);
17798 if (!ctx || !ctx->current || !ctx->current->layout)
17799 return;
17800
17801 win = ctx->current;
17802 layout = win->layout;
17803 layout->row.item = rect;
17804}
17805NK_API struct nk_rect
17807{
17808 struct nk_rect ret;
17809 struct nk_window *win;
17810 struct nk_panel *layout;
17811
17812 NK_ASSERT(ctx);
17813 NK_ASSERT(ctx->current);
17814 NK_ASSERT(ctx->current->layout);
17815 win = ctx->current;
17816 layout = win->layout;
17817
17818 ret.x = layout->clip.x;
17819 ret.y = layout->clip.y;
17820 ret.w = layout->clip.w;
17821 ret.h = layout->row.height;
17822 return ret;
17823}
17824NK_API struct nk_rect
17826{
17827 struct nk_rect ret;
17828 struct nk_window *win;
17829 struct nk_panel *layout;
17830
17831 NK_ASSERT(ctx);
17832 NK_ASSERT(ctx->current);
17833 NK_ASSERT(ctx->current->layout);
17834 win = ctx->current;
17835 layout = win->layout;
17836
17837 ret.x = layout->at_x;
17838 ret.y = layout->at_y;
17839 ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
17840 ret.h = layout->row.height;
17841 return ret;
17842}
17843NK_API struct nk_vec2
17844nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
17845{
17846 struct nk_window *win;
17847 struct nk_panel *layout;
17848
17849 NK_ASSERT(ctx);
17850 NK_ASSERT(ctx->current);
17851 NK_ASSERT(ctx->current->layout);
17852 win = ctx->current;
17853 layout = win->layout;
17854
17855 ret.x += layout->at_x - (float)*layout->offset_x;
17856 ret.y += layout->at_y - (float)*layout->offset_y;
17857 return ret;
17858}
17859NK_API struct nk_vec2
17860nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
17861{
17862 struct nk_window *win;
17863 struct nk_panel *layout;
17864
17865 NK_ASSERT(ctx);
17866 NK_ASSERT(ctx->current);
17867 NK_ASSERT(ctx->current->layout);
17868 win = ctx->current;
17869 layout = win->layout;
17870
17871 ret.x += -layout->at_x + (float)*layout->offset_x;
17872 ret.y += -layout->at_y + (float)*layout->offset_y;
17873 return ret;
17874}
17875NK_API struct nk_rect
17876nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret)
17877{
17878 struct nk_window *win;
17879 struct nk_panel *layout;
17880
17881 NK_ASSERT(ctx);
17882 NK_ASSERT(ctx->current);
17883 NK_ASSERT(ctx->current->layout);
17884 win = ctx->current;
17885 layout = win->layout;
17886
17887 ret.x += layout->at_x - (float)*layout->offset_x;
17888 ret.y += layout->at_y - (float)*layout->offset_y;
17889 return ret;
17890}
17891NK_API struct nk_rect
17892nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret)
17893{
17894 struct nk_window *win;
17895 struct nk_panel *layout;
17896
17897 NK_ASSERT(ctx);
17898 NK_ASSERT(ctx->current);
17899 NK_ASSERT(ctx->current->layout);
17900 win = ctx->current;
17901 layout = win->layout;
17902
17903 ret.x += -layout->at_x + (float)*layout->offset_x;
17904 ret.y += -layout->at_y + (float)*layout->offset_y;
17905 return ret;
17906}
17907NK_LIB void
17908nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
17909{
17910 struct nk_panel *layout = win->layout;
17911 struct nk_vec2 spacing = ctx->style.window.spacing;
17912 const float row_height = layout->row.height - spacing.y;
17913 nk_panel_layout(ctx, win, row_height, layout->row.columns);
17914}
17915NK_LIB void
17916nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
17917 struct nk_window *win, int modify)
17918{
17919 struct nk_panel *layout;
17920 const struct nk_style *style;
17921
17922 struct nk_vec2 spacing;
17923 struct nk_vec2 padding;
17924
17925 float item_offset = 0;
17926 float item_width = 0;
17927 float item_spacing = 0;
17928 float panel_space = 0;
17929
17930 NK_ASSERT(ctx);
17931 NK_ASSERT(ctx->current);
17932 NK_ASSERT(ctx->current->layout);
17933 if (!ctx || !ctx->current || !ctx->current->layout)
17934 return;
17935
17936 win = ctx->current;
17937 layout = win->layout;
17938 style = &ctx->style;
17939 NK_ASSERT(bounds);
17940
17941 spacing = style->window.spacing;
17942 padding = nk_panel_get_padding(style, layout->type);
17943 panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
17944 layout->bounds.w, layout->row.columns);
17945
17946 #define NK_FRAC(x) (x - (int)x) /* will be used to remove fookin gaps */
17947 /* calculate the width of one item inside the current layout space */
17948 switch (layout->row.type) {
17950 /* scaling fixed size widgets item width */
17951 float w = NK_MAX(1.0f,panel_space) / (float)layout->row.columns;
17952 item_offset = (float)layout->row.index * w;
17953 item_width = w + NK_FRAC(item_offset);
17954 item_spacing = (float)layout->row.index * spacing.x;
17955 } break;
17956 case NK_LAYOUT_DYNAMIC_ROW: {
17957 /* scaling single ratio widget width */
17958 float w = layout->row.item_width * panel_space;
17959 item_offset = layout->row.item_offset;
17960 item_width = w + NK_FRAC(item_offset);
17961 item_spacing = 0;
17962
17963 if (modify) {
17964 layout->row.item_offset += w + spacing.x;
17965 layout->row.filled += layout->row.item_width;
17966 layout->row.index = 0;
17967 }
17968 } break;
17970 /* panel width depended free widget placing */
17971 bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
17972 bounds->x -= (float)*layout->offset_x;
17973 bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
17974 bounds->y -= (float)*layout->offset_y;
17975 bounds->w = layout->bounds.w * layout->row.item.w + NK_FRAC(bounds->x);
17976 bounds->h = layout->row.height * layout->row.item.h + NK_FRAC(bounds->y);
17977 return;
17978 }
17979 case NK_LAYOUT_DYNAMIC: {
17980 /* scaling arrays of panel width ratios for every widget */
17981 float ratio, w;
17982 NK_ASSERT(layout->row.ratio);
17983 ratio = (layout->row.ratio[layout->row.index] < 0) ?
17984 layout->row.item_width : layout->row.ratio[layout->row.index];
17985
17986 w = (ratio * panel_space);
17987 item_spacing = (float)layout->row.index * spacing.x;
17988 item_offset = layout->row.item_offset;
17989 item_width = w + NK_FRAC(item_offset);
17990
17991 if (modify) {
17992 layout->row.item_offset += w;
17993 layout->row.filled += ratio;
17994 }
17995 } break;
17997 /* non-scaling fixed widgets item width */
17998 item_width = layout->row.item_width;
17999 item_offset = (float)layout->row.index * item_width;
18000 item_spacing = (float)layout->row.index * spacing.x;
18001 } break;
18002 case NK_LAYOUT_STATIC_ROW: {
18003 /* scaling single ratio widget width */
18004 item_width = layout->row.item_width;
18005 item_offset = layout->row.item_offset;
18006 item_spacing = (float)layout->row.index * spacing.x;
18007 if (modify) layout->row.item_offset += item_width;
18008 } break;
18009 case NK_LAYOUT_STATIC_FREE: {
18010 /* free widget placing */
18011 bounds->x = layout->at_x + layout->row.item.x;
18012 bounds->w = layout->row.item.w;
18013 if (((bounds->x + bounds->w) > layout->max_x) && modify)
18014 layout->max_x = (bounds->x + bounds->w);
18015 bounds->x -= (float)*layout->offset_x;
18016 bounds->y = layout->at_y + layout->row.item.y;
18017 bounds->y -= (float)*layout->offset_y;
18018 bounds->h = layout->row.item.h;
18019 return;
18020 }
18021 case NK_LAYOUT_STATIC: {
18022 /* non-scaling array of panel pixel width for every widget */
18023 item_spacing = (float)layout->row.index * spacing.x;
18024 item_width = layout->row.ratio[layout->row.index];
18025 item_offset = layout->row.item_offset;
18026 if (modify) layout->row.item_offset += item_width;
18027 } break;
18028 case NK_LAYOUT_TEMPLATE: {
18029 /* stretchy row layout with combined dynamic/static widget width*/
18030 float w;
18031 NK_ASSERT(layout->row.index < layout->row.columns);
18032 NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
18033 w = layout->row.templates[layout->row.index];
18034 item_offset = layout->row.item_offset;
18035 item_width = w + NK_FRAC(item_offset);
18036 item_spacing = (float)layout->row.index * spacing.x;
18037 if (modify) layout->row.item_offset += w;
18038 } break;
18039 #undef NK_FRAC
18040 default: NK_ASSERT(0); break;
18041 };
18042
18043 /* set the bounds of the newly allocated widget */
18044 bounds->w = item_width;
18045 bounds->h = layout->row.height - spacing.y;
18046 bounds->y = layout->at_y - (float)*layout->offset_y;
18047 bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
18048 if (((bounds->x + bounds->w) > layout->max_x) && modify)
18049 layout->max_x = bounds->x + bounds->w;
18050 bounds->x -= (float)*layout->offset_x;
18051}
18052NK_LIB void
18053nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
18054{
18055 struct nk_window *win;
18056 struct nk_panel *layout;
18057
18058 NK_ASSERT(ctx);
18059 NK_ASSERT(ctx->current);
18060 NK_ASSERT(ctx->current->layout);
18061 if (!ctx || !ctx->current || !ctx->current->layout)
18062 return;
18063
18064 /* check if the end of the row has been hit and begin new row if so */
18065 win = ctx->current;
18066 layout = win->layout;
18067 if (layout->row.index >= layout->row.columns)
18068 nk_panel_alloc_row(ctx, win);
18069
18070 /* calculate widget position and size */
18071 nk_layout_widget_space(bounds, ctx, win, nk_true);
18072 layout->row.index++;
18073}
18074NK_LIB void
18075nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
18076{
18077 float y;
18078 int index;
18079 struct nk_window *win;
18080 struct nk_panel *layout;
18081
18082 NK_ASSERT(ctx);
18083 NK_ASSERT(ctx->current);
18084 NK_ASSERT(ctx->current->layout);
18085 if (!ctx || !ctx->current || !ctx->current->layout)
18086 return;
18087
18088 win = ctx->current;
18089 layout = win->layout;
18090 y = layout->at_y;
18091 index = layout->row.index;
18092 if (layout->row.index >= layout->row.columns) {
18093 layout->at_y += layout->row.height;
18094 layout->row.index = 0;
18095 }
18096 nk_layout_widget_space(bounds, ctx, win, nk_false);
18097 if (!layout->row.index) {
18098 bounds->x -= layout->row.item_offset;
18099 }
18100 layout->at_y = y;
18101 layout->row.index = index;
18102}
18103
18104
18105
18106
18107/* ===============================================================
18108 *
18109 * TREE
18110 *
18111 * ===============================================================*/
18112NK_INTERN int
18113nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
18114 struct nk_image *img, const char *title, enum nk_collapse_states *state)
18115{
18116 struct nk_window *win;
18117 struct nk_panel *layout;
18118 const struct nk_style *style;
18119 struct nk_command_buffer *out;
18120 const struct nk_input *in;
18121 const struct nk_style_button *button;
18122 enum nk_symbol_type symbol;
18123 float row_height;
18124
18125 struct nk_vec2 item_spacing;
18126 struct nk_rect header = {0,0,0,0};
18127 struct nk_rect sym = {0,0,0,0};
18128 struct nk_text text;
18129
18130 nk_flags ws = 0;
18131 enum nk_widget_layout_states widget_state;
18132
18133 NK_ASSERT(ctx);
18134 NK_ASSERT(ctx->current);
18135 NK_ASSERT(ctx->current->layout);
18136 if (!ctx || !ctx->current || !ctx->current->layout)
18137 return 0;
18138
18139 /* cache some data */
18140 win = ctx->current;
18141 layout = win->layout;
18142 out = &win->buffer;
18143 style = &ctx->style;
18144 item_spacing = style->window.spacing;
18145
18146 /* calculate header bounds and draw background */
18147 row_height = style->font->height + 2 * style->tab.padding.y;
18148 nk_layout_set_min_row_height(ctx, row_height);
18149 nk_layout_row_dynamic(ctx, row_height, 1);
18151
18152 widget_state = nk_widget(&header, ctx);
18153 if (type == NK_TREE_TAB) {
18154 const struct nk_style_item *background = &style->tab.background;
18155 if (background->type == NK_STYLE_ITEM_IMAGE) {
18156 nk_draw_image(out, header, &background->data.image, nk_white);
18157 text.background = nk_rgba(0,0,0,0);
18158 } else {
18159 text.background = background->data.color;
18160 nk_fill_rect(out, header, 0, style->tab.border_color);
18161 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
18162 style->tab.rounding, background->data.color);
18163 }
18164 } else text.background = style->window.background;
18165
18166 /* update node state */
18167 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
18168 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
18169 if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
18170 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
18171
18172 /* select correct button style */
18173 if (*state == NK_MAXIMIZED) {
18174 symbol = style->tab.sym_maximize;
18175 if (type == NK_TREE_TAB)
18176 button = &style->tab.tab_maximize_button;
18177 else button = &style->tab.node_maximize_button;
18178 } else {
18179 symbol = style->tab.sym_minimize;
18180 if (type == NK_TREE_TAB)
18181 button = &style->tab.tab_minimize_button;
18182 else button = &style->tab.node_minimize_button;
18183 }
18184
18185 {/* draw triangle button */
18186 sym.w = sym.h = style->font->height;
18187 sym.y = header.y + style->tab.padding.y;
18188 sym.x = header.x + style->tab.padding.x;
18189 nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
18190 button, 0, style->font);
18191
18192 if (img) {
18193 /* draw optional image icon */
18194 sym.x = sym.x + sym.w + 4 * item_spacing.x;
18195 nk_draw_image(&win->buffer, sym, img, nk_white);
18196 sym.w = style->font->height + style->tab.spacing.x;}
18197 }
18198
18199 {/* draw label */
18200 struct nk_rect label;
18201 header.w = NK_MAX(header.w, sym.w + item_spacing.x);
18202 label.x = sym.x + sym.w + item_spacing.x;
18203 label.y = sym.y;
18204 label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
18205 label.h = style->font->height;
18206 text.text = style->tab.text;
18207 text.padding = nk_vec2(0,0);
18208 nk_widget_text(out, label, title, nk_strlen(title), &text,
18209 NK_TEXT_LEFT, style->font);}
18210
18211 /* increase x-axis cursor widget position pointer */
18212 if (*state == NK_MAXIMIZED) {
18213 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
18214 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
18215 layout->bounds.w -= (style->tab.indent + style->window.padding.x);
18216 layout->row.tree_depth++;
18217 return nk_true;
18218 } else return nk_false;
18219}
18220NK_INTERN int
18221nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
18222 struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
18223 const char *hash, int len, int line)
18224{
18225 struct nk_window *win = ctx->current;
18226 int title_len = 0;
18227 nk_hash tree_hash = 0;
18228 nk_uint *state = 0;
18229
18230 /* retrieve tree state from internal widget state tables */
18231 if (!hash) {
18232 title_len = (int)nk_strlen(title);
18233 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
18234 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
18235 state = nk_find_value(win, tree_hash);
18236 if (!state) {
18237 state = nk_add_value(ctx, win, tree_hash, 0);
18238 *state = initial_state;
18239 }
18240 return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
18241}
18242NK_API int
18243nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
18244 const char *title, enum nk_collapse_states *state)
18245{
18246 return nk_tree_state_base(ctx, type, 0, title, state);
18247}
18248NK_API int
18249nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
18250 struct nk_image img, const char *title, enum nk_collapse_states *state)
18251{
18252 return nk_tree_state_base(ctx, type, &img, title, state);
18253}
18254NK_API void
18255nk_tree_state_pop(struct nk_context *ctx)
18256{
18257 struct nk_window *win = 0;
18258 struct nk_panel *layout = 0;
18259
18260 NK_ASSERT(ctx);
18261 NK_ASSERT(ctx->current);
18262 NK_ASSERT(ctx->current->layout);
18263 if (!ctx || !ctx->current || !ctx->current->layout)
18264 return;
18265
18266 win = ctx->current;
18267 layout = win->layout;
18268 layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
18269 layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
18270 NK_ASSERT(layout->row.tree_depth);
18271 layout->row.tree_depth--;
18272}
18273NK_API int
18275 const char *title, enum nk_collapse_states initial_state,
18276 const char *hash, int len, int line)
18277{
18278 return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);
18279}
18280NK_API int
18282 struct nk_image img, const char *title, enum nk_collapse_states initial_state,
18283 const char *hash, int len,int seed)
18284{
18285 return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);
18286}
18287NK_API void
18288nk_tree_pop(struct nk_context *ctx)
18289{
18290 nk_tree_state_pop(ctx);
18291}
18292NK_INTERN int
18293nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type,
18294 struct nk_image *img, const char *title, int title_len,
18295 enum nk_collapse_states *state, int *selected)
18296{
18297 struct nk_window *win;
18298 struct nk_panel *layout;
18299 const struct nk_style *style;
18300 struct nk_command_buffer *out;
18301 const struct nk_input *in;
18302 const struct nk_style_button *button;
18303 enum nk_symbol_type symbol;
18304 float row_height;
18305 struct nk_vec2 padding;
18306
18307 int text_len;
18308 float text_width;
18309
18310 struct nk_vec2 item_spacing;
18311 struct nk_rect header = {0,0,0,0};
18312 struct nk_rect sym = {0,0,0,0};
18313 struct nk_text text;
18314
18315 nk_flags ws = 0;
18316 enum nk_widget_layout_states widget_state;
18317
18318 NK_ASSERT(ctx);
18319 NK_ASSERT(ctx->current);
18320 NK_ASSERT(ctx->current->layout);
18321 if (!ctx || !ctx->current || !ctx->current->layout)
18322 return 0;
18323
18324 /* cache some data */
18325 win = ctx->current;
18326 layout = win->layout;
18327 out = &win->buffer;
18328 style = &ctx->style;
18329 item_spacing = style->window.spacing;
18330 padding = style->selectable.padding;
18331
18332 /* calculate header bounds and draw background */
18333 row_height = style->font->height + 2 * style->tab.padding.y;
18334 nk_layout_set_min_row_height(ctx, row_height);
18335 nk_layout_row_dynamic(ctx, row_height, 1);
18337
18338 widget_state = nk_widget(&header, ctx);
18339 if (type == NK_TREE_TAB) {
18340 const struct nk_style_item *background = &style->tab.background;
18341 if (background->type == NK_STYLE_ITEM_IMAGE) {
18342 nk_draw_image(out, header, &background->data.image, nk_white);
18343 text.background = nk_rgba(0,0,0,0);
18344 } else {
18345 text.background = background->data.color;
18346 nk_fill_rect(out, header, 0, style->tab.border_color);
18347 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
18348 style->tab.rounding, background->data.color);
18349 }
18350 } else text.background = style->window.background;
18351
18352 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
18353 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
18354
18355 /* select correct button style */
18356 if (*state == NK_MAXIMIZED) {
18357 symbol = style->tab.sym_maximize;
18358 if (type == NK_TREE_TAB)
18359 button = &style->tab.tab_maximize_button;
18360 else button = &style->tab.node_maximize_button;
18361 } else {
18362 symbol = style->tab.sym_minimize;
18363 if (type == NK_TREE_TAB)
18364 button = &style->tab.tab_minimize_button;
18365 else button = &style->tab.node_minimize_button;
18366 }
18367 {/* draw triangle button */
18368 sym.w = sym.h = style->font->height;
18369 sym.y = header.y + style->tab.padding.y;
18370 sym.x = header.x + style->tab.padding.x;
18371 if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font))
18372 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;}
18373
18374 /* draw label */
18375 {nk_flags dummy = 0;
18376 struct nk_rect label;
18377 /* calculate size of the text and tooltip */
18378 text_len = nk_strlen(title);
18379 text_width = style->font->width(style->font->userdata, style->font->height, title, text_len);
18380 text_width += (4 * padding.x);
18381
18382 header.w = NK_MAX(header.w, sym.w + item_spacing.x);
18383 label.x = sym.x + sym.w + item_spacing.x;
18384 label.y = sym.y;
18385 label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width);
18386 label.h = style->font->height;
18387
18388 if (img) {
18389 nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
18390 selected, img, &style->selectable, in, style->font);
18391 } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
18392 selected, &style->selectable, in, style->font);
18393 }
18394 /* increase x-axis cursor widget position pointer */
18395 if (*state == NK_MAXIMIZED) {
18396 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
18397 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
18398 layout->bounds.w -= (style->tab.indent + style->window.padding.x);
18399 layout->row.tree_depth++;
18400 return nk_true;
18401 } else return nk_false;
18402}
18403NK_INTERN int
18404nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type,
18405 struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
18406 int *selected, const char *hash, int len, int line)
18407{
18408 struct nk_window *win = ctx->current;
18409 int title_len = 0;
18410 nk_hash tree_hash = 0;
18411 nk_uint *state = 0;
18412
18413 /* retrieve tree state from internal widget state tables */
18414 if (!hash) {
18415 title_len = (int)nk_strlen(title);
18416 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
18417 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
18418 state = nk_find_value(win, tree_hash);
18419 if (!state) {
18420 state = nk_add_value(ctx, win, tree_hash, 0);
18421 *state = initial_state;
18422 } return nk_tree_element_image_push_hashed_base(ctx, type, img, title,
18423 nk_strlen(title), (enum nk_collapse_states*)state, selected);
18424}
18425NK_API int
18427 const char *title, enum nk_collapse_states initial_state,
18428 int *selected, const char *hash, int len, int seed)
18429{
18430 return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed);
18431}
18432NK_API int
18434 struct nk_image img, const char *title, enum nk_collapse_states initial_state,
18435 int *selected, const char *hash, int len,int seed)
18436{
18437 return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed);
18438}
18439NK_API void
18441{
18442 nk_tree_state_pop(ctx);
18443}
18444
18445
18446
18447
18448/* ===============================================================
18449 *
18450 * GROUP
18451 *
18452 * ===============================================================*/
18453NK_API int
18455 nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
18456{
18457 struct nk_rect bounds;
18458 struct nk_window panel;
18459 struct nk_window *win;
18460
18461 win = ctx->current;
18462 nk_panel_alloc_space(&bounds, ctx);
18463 {const struct nk_rect *c = &win->layout->clip;
18464 if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
18465 !(flags & NK_WINDOW_MOVABLE)) {
18466 return 0;
18467 }}
18468 if (win->flags & NK_WINDOW_ROM)
18469 flags |= NK_WINDOW_ROM;
18470
18471 /* initialize a fake window to create the panel from */
18472 nk_zero(&panel, sizeof(panel));
18473 panel.bounds = bounds;
18474 panel.flags = flags;
18475 panel.scrollbar.x = *x_offset;
18476 panel.scrollbar.y = *y_offset;
18477 panel.buffer = win->buffer;
18478 panel.layout = (struct nk_panel*)nk_create_panel(ctx);
18479 ctx->current = &panel;
18480 nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
18481
18482 win->buffer = panel.buffer;
18483 win->buffer.clip = panel.layout->clip;
18484 panel.layout->offset_x = x_offset;
18485 panel.layout->offset_y = y_offset;
18486 panel.layout->parent = win->layout;
18487 win->layout = panel.layout;
18488
18489 ctx->current = win;
18490 if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
18491 (panel.layout->flags & NK_WINDOW_MINIMIZED))
18492 {
18493 nk_flags f = panel.layout->flags;
18495 if (f & NK_WINDOW_CLOSED)
18496 return NK_WINDOW_CLOSED;
18497 if (f & NK_WINDOW_MINIMIZED)
18498 return NK_WINDOW_MINIMIZED;
18499 }
18500 return 1;
18501}
18502NK_API void
18504{
18505 struct nk_window *win;
18506 struct nk_panel *parent;
18507 struct nk_panel *g;
18508
18509 struct nk_rect clip;
18510 struct nk_window pan;
18511 struct nk_vec2 panel_padding;
18512
18513 NK_ASSERT(ctx);
18514 NK_ASSERT(ctx->current);
18515 if (!ctx || !ctx->current)
18516 return;
18517
18518 /* make sure nk_group_begin was called correctly */
18519 NK_ASSERT(ctx->current);
18520 win = ctx->current;
18521 NK_ASSERT(win->layout);
18522 g = win->layout;
18523 NK_ASSERT(g->parent);
18524 parent = g->parent;
18525
18526 /* dummy window */
18527 nk_zero_struct(pan);
18528 panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
18529 pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
18530 pan.bounds.x = g->bounds.x - panel_padding.x;
18531 pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
18532 pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
18533 if (g->flags & NK_WINDOW_BORDER) {
18534 pan.bounds.x -= g->border;
18535 pan.bounds.y -= g->border;
18536 pan.bounds.w += 2*g->border;
18537 pan.bounds.h += 2*g->border;
18538 }
18539 if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
18540 pan.bounds.w += ctx->style.window.scrollbar_size.x;
18541 pan.bounds.h += ctx->style.window.scrollbar_size.y;
18542 }
18543 pan.scrollbar.x = *g->offset_x;
18544 pan.scrollbar.y = *g->offset_y;
18545 pan.flags = g->flags;
18546 pan.buffer = win->buffer;
18547 pan.layout = g;
18548 pan.parent = win;
18549 ctx->current = &pan;
18550
18551 /* make sure group has correct clipping rectangle */
18552 nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
18553 pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
18554 nk_push_scissor(&pan.buffer, clip);
18555 nk_end(ctx);
18556
18557 win->buffer = pan.buffer;
18558 nk_push_scissor(&win->buffer, parent->clip);
18559 ctx->current = win;
18560 win->layout = parent;
18561 g->bounds = pan.bounds;
18562 return;
18563}
18564NK_API int
18566 struct nk_scroll *scroll, const char *title, nk_flags flags)
18567{
18568 return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);
18569}
18570NK_API int
18571nk_group_begin_titled(struct nk_context *ctx, const char *id,
18572 const char *title, nk_flags flags)
18573{
18574 int id_len;
18575 nk_hash id_hash;
18576 struct nk_window *win;
18577 nk_uint *x_offset;
18578 nk_uint *y_offset;
18579
18580 NK_ASSERT(ctx);
18581 NK_ASSERT(id);
18582 NK_ASSERT(ctx->current);
18583 NK_ASSERT(ctx->current->layout);
18584 if (!ctx || !ctx->current || !ctx->current->layout || !id)
18585 return 0;
18586
18587 /* find persistent group scrollbar value */
18588 win = ctx->current;
18589 id_len = (int)nk_strlen(id);
18590 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
18591 x_offset = nk_find_value(win, id_hash);
18592 if (!x_offset) {
18593 x_offset = nk_add_value(ctx, win, id_hash, 0);
18594 y_offset = nk_add_value(ctx, win, id_hash+1, 0);
18595
18596 NK_ASSERT(x_offset);
18597 NK_ASSERT(y_offset);
18598 if (!x_offset || !y_offset) return 0;
18599 *x_offset = *y_offset = 0;
18600 } else y_offset = nk_find_value(win, id_hash+1);
18601 return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
18602}
18603NK_API int
18604nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
18605{
18606 return nk_group_begin_titled(ctx, title, title, flags);
18607}
18608NK_API void
18609nk_group_end(struct nk_context *ctx)
18610{
18612}
18613NK_API void
18614nk_group_get_scroll(struct nk_context *ctx, const char *id, nk_uint *x_offset, nk_uint *y_offset)
18615{
18616 int id_len;
18617 nk_hash id_hash;
18618 struct nk_window *win;
18619 nk_uint *x_offset_ptr;
18620 nk_uint *y_offset_ptr;
18621
18622 NK_ASSERT(ctx);
18623 NK_ASSERT(id);
18624 NK_ASSERT(ctx->current);
18625 NK_ASSERT(ctx->current->layout);
18626 if (!ctx || !ctx->current || !ctx->current->layout || !id)
18627 return;
18628
18629 /* find persistent group scrollbar value */
18630 win = ctx->current;
18631 id_len = (int)nk_strlen(id);
18632 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
18633 x_offset_ptr = nk_find_value(win, id_hash);
18634 if (!x_offset_ptr) {
18635 x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
18636 y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
18637
18638 NK_ASSERT(x_offset_ptr);
18639 NK_ASSERT(y_offset_ptr);
18640 if (!x_offset_ptr || !y_offset_ptr) return;
18641 *x_offset_ptr = *y_offset_ptr = 0;
18642 } else y_offset_ptr = nk_find_value(win, id_hash+1);
18643 if (x_offset)
18644 *x_offset = *x_offset_ptr;
18645 if (y_offset)
18646 *y_offset = *y_offset_ptr;
18647}
18648NK_API void
18649nk_group_set_scroll(struct nk_context *ctx, const char *id, nk_uint x_offset, nk_uint y_offset)
18650{
18651 int id_len;
18652 nk_hash id_hash;
18653 struct nk_window *win;
18654 nk_uint *x_offset_ptr;
18655 nk_uint *y_offset_ptr;
18656
18657 NK_ASSERT(ctx);
18658 NK_ASSERT(id);
18659 NK_ASSERT(ctx->current);
18660 NK_ASSERT(ctx->current->layout);
18661 if (!ctx || !ctx->current || !ctx->current->layout || !id)
18662 return;
18663
18664 /* find persistent group scrollbar value */
18665 win = ctx->current;
18666 id_len = (int)nk_strlen(id);
18667 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
18668 x_offset_ptr = nk_find_value(win, id_hash);
18669 if (!x_offset_ptr) {
18670 x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
18671 y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
18672
18673 NK_ASSERT(x_offset_ptr);
18674 NK_ASSERT(y_offset_ptr);
18675 if (!x_offset_ptr || !y_offset_ptr) return;
18676 *x_offset_ptr = *y_offset_ptr = 0;
18677 } else y_offset_ptr = nk_find_value(win, id_hash+1);
18678 *x_offset_ptr = x_offset;
18679 *y_offset_ptr = y_offset;
18680}
18681
18682
18683
18684/* ===============================================================
18685 *
18686 * LIST VIEW
18687 *
18688 * ===============================================================*/
18689NK_API int
18690nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
18691 const char *title, nk_flags flags, int row_height, int row_count)
18692{
18693 int title_len;
18694 nk_hash title_hash;
18695 nk_uint *x_offset;
18696 nk_uint *y_offset;
18697
18698 int result;
18699 struct nk_window *win;
18700 struct nk_panel *layout;
18701 const struct nk_style *style;
18702 struct nk_vec2 item_spacing;
18703
18704 NK_ASSERT(ctx);
18705 NK_ASSERT(view);
18706 NK_ASSERT(title);
18707 if (!ctx || !view || !title) return 0;
18708
18709 win = ctx->current;
18710 style = &ctx->style;
18711 item_spacing = style->window.spacing;
18712 row_height += NK_MAX(0, (int)item_spacing.y);
18713
18714 /* find persistent list view scrollbar offset */
18715 title_len = (int)nk_strlen(title);
18716 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
18717 x_offset = nk_find_value(win, title_hash);
18718 if (!x_offset) {
18719 x_offset = nk_add_value(ctx, win, title_hash, 0);
18720 y_offset = nk_add_value(ctx, win, title_hash+1, 0);
18721
18722 NK_ASSERT(x_offset);
18723 NK_ASSERT(y_offset);
18724 if (!x_offset || !y_offset) return 0;
18725 *x_offset = *y_offset = 0;
18726 } else y_offset = nk_find_value(win, title_hash+1);
18727 view->scroll_value = *y_offset;
18728 view->scroll_pointer = y_offset;
18729
18730 *y_offset = 0;
18731 result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
18732 win = ctx->current;
18733 layout = win->layout;
18734
18735 view->total_height = row_height * NK_MAX(row_count,1);
18736 view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
18737 view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0);
18738 view->count = NK_MIN(view->count, row_count - view->begin);
18739 view->end = view->begin + view->count;
18740 view->ctx = ctx;
18741 return result;
18742}
18743NK_API void
18744nk_list_view_end(struct nk_list_view *view)
18745{
18746 struct nk_context *ctx;
18747 struct nk_window *win;
18748 struct nk_panel *layout;
18749
18750 NK_ASSERT(view);
18751 NK_ASSERT(view->ctx);
18752 NK_ASSERT(view->scroll_pointer);
18753 if (!view || !view->ctx) return;
18754
18755 ctx = view->ctx;
18756 win = ctx->current;
18757 layout = win->layout;
18758 layout->at_y = layout->bounds.y + (float)view->total_height;
18759 *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
18760 nk_group_end(view->ctx);
18761}
18762
18763
18764
18765
18766/* ===============================================================
18767 *
18768 * WIDGET
18769 *
18770 * ===============================================================*/
18771NK_API struct nk_rect
18772nk_widget_bounds(struct nk_context *ctx)
18773{
18774 struct nk_rect bounds;
18775 NK_ASSERT(ctx);
18776 NK_ASSERT(ctx->current);
18777 if (!ctx || !ctx->current)
18778 return nk_rect(0,0,0,0);
18779 nk_layout_peek(&bounds, ctx);
18780 return bounds;
18781}
18782NK_API struct nk_vec2
18783nk_widget_position(struct nk_context *ctx)
18784{
18785 struct nk_rect bounds;
18786 NK_ASSERT(ctx);
18787 NK_ASSERT(ctx->current);
18788 if (!ctx || !ctx->current)
18789 return nk_vec2(0,0);
18790
18791 nk_layout_peek(&bounds, ctx);
18792 return nk_vec2(bounds.x, bounds.y);
18793}
18794NK_API struct nk_vec2
18795nk_widget_size(struct nk_context *ctx)
18796{
18797 struct nk_rect bounds;
18798 NK_ASSERT(ctx);
18799 NK_ASSERT(ctx->current);
18800 if (!ctx || !ctx->current)
18801 return nk_vec2(0,0);
18802
18803 nk_layout_peek(&bounds, ctx);
18804 return nk_vec2(bounds.w, bounds.h);
18805}
18806NK_API float
18807nk_widget_width(struct nk_context *ctx)
18808{
18809 struct nk_rect bounds;
18810 NK_ASSERT(ctx);
18811 NK_ASSERT(ctx->current);
18812 if (!ctx || !ctx->current)
18813 return 0;
18814
18815 nk_layout_peek(&bounds, ctx);
18816 return bounds.w;
18817}
18818NK_API float
18819nk_widget_height(struct nk_context *ctx)
18820{
18821 struct nk_rect bounds;
18822 NK_ASSERT(ctx);
18823 NK_ASSERT(ctx->current);
18824 if (!ctx || !ctx->current)
18825 return 0;
18826
18827 nk_layout_peek(&bounds, ctx);
18828 return bounds.h;
18829}
18830NK_API int
18832{
18833 struct nk_rect c, v;
18834 struct nk_rect bounds;
18835 NK_ASSERT(ctx);
18836 NK_ASSERT(ctx->current);
18837 if (!ctx || !ctx->current || ctx->active != ctx->current)
18838 return 0;
18839
18840 c = ctx->current->layout->clip;
18841 c.x = (float)((int)c.x);
18842 c.y = (float)((int)c.y);
18843 c.w = (float)((int)c.w);
18844 c.h = (float)((int)c.h);
18845
18846 nk_layout_peek(&bounds, ctx);
18847 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
18848 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
18849 return 0;
18850 return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
18851}
18852NK_API int
18854{
18855 struct nk_rect c, v;
18856 struct nk_rect bounds;
18857 NK_ASSERT(ctx);
18858 NK_ASSERT(ctx->current);
18859 if (!ctx || !ctx->current || ctx->active != ctx->current)
18860 return 0;
18861
18862 c = ctx->current->layout->clip;
18863 c.x = (float)((int)c.x);
18864 c.y = (float)((int)c.y);
18865 c.w = (float)((int)c.w);
18866 c.h = (float)((int)c.h);
18867
18868 nk_layout_peek(&bounds, ctx);
18869 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
18870 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
18871 return 0;
18872 return nk_input_mouse_clicked(&ctx->input, btn, bounds);
18873}
18874NK_API int
18875nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
18876{
18877 struct nk_rect c, v;
18878 struct nk_rect bounds;
18879 NK_ASSERT(ctx);
18880 NK_ASSERT(ctx->current);
18881 if (!ctx || !ctx->current || ctx->active != ctx->current)
18882 return 0;
18883
18884 c = ctx->current->layout->clip;
18885 c.x = (float)((int)c.x);
18886 c.y = (float)((int)c.y);
18887 c.w = (float)((int)c.w);
18888 c.h = (float)((int)c.h);
18889
18890 nk_layout_peek(&bounds, ctx);
18891 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
18892 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
18893 return 0;
18894 return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
18895}
18897nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
18898{
18899 struct nk_rect c, v;
18900 struct nk_window *win;
18901 struct nk_panel *layout;
18902 const struct nk_input *in;
18903
18904 NK_ASSERT(ctx);
18905 NK_ASSERT(ctx->current);
18906 NK_ASSERT(ctx->current->layout);
18907 if (!ctx || !ctx->current || !ctx->current->layout)
18908 return NK_WIDGET_INVALID;
18909
18910 /* allocate space and check if the widget needs to be updated and drawn */
18911 nk_panel_alloc_space(bounds, ctx);
18912 win = ctx->current;
18913 layout = win->layout;
18914 in = &ctx->input;
18915 c = layout->clip;
18916
18917 /* if one of these triggers you forgot to add an `if` condition around either
18918 a window, group, popup, combobox or contextual menu `begin` and `end` block.
18919 Example:
18920 if (nk_begin(...) {...} nk_end(...); or
18921 if (nk_group_begin(...) { nk_group_end(...);} */
18922 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
18923 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
18924 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
18925
18926 /* need to convert to int here to remove floating point errors */
18927 bounds->x = (float)((int)bounds->x);
18928 bounds->y = (float)((int)bounds->y);
18929 bounds->w = (float)((int)bounds->w);
18930 bounds->h = (float)((int)bounds->h);
18931
18932 c.x = (float)((int)c.x);
18933 c.y = (float)((int)c.y);
18934 c.w = (float)((int)c.w);
18935 c.h = (float)((int)c.h);
18936
18937 nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
18938 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
18939 return NK_WIDGET_INVALID;
18940 if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
18941 return NK_WIDGET_ROM;
18942 return NK_WIDGET_VALID;
18943}
18945nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
18946 struct nk_vec2 item_padding)
18947{
18948 /* update the bounds to stand without padding */
18949 struct nk_window *win;
18950 struct nk_style *style;
18951 struct nk_panel *layout;
18952 enum nk_widget_layout_states state;
18953 struct nk_vec2 panel_padding;
18954
18955 NK_ASSERT(ctx);
18956 NK_ASSERT(ctx->current);
18957 NK_ASSERT(ctx->current->layout);
18958 if (!ctx || !ctx->current || !ctx->current->layout)
18959 return NK_WIDGET_INVALID;
18960
18961 win = ctx->current;
18962 style = &ctx->style;
18963 layout = win->layout;
18964 state = nk_widget(bounds, ctx);
18965
18966 panel_padding = nk_panel_get_padding(style, layout->type);
18967 if (layout->row.index == 1) {
18968 bounds->w += panel_padding.x;
18969 bounds->x -= panel_padding.x;
18970 } else bounds->x -= item_padding.x;
18971
18972 if (layout->row.index == layout->row.columns)
18973 bounds->w += panel_padding.x;
18974 else bounds->w += item_padding.x;
18975 return state;
18976}
18977NK_API void
18978nk_spacing(struct nk_context *ctx, int cols)
18979{
18980 struct nk_window *win;
18981 struct nk_panel *layout;
18982 struct nk_rect none;
18983 int i, index, rows;
18984
18985 NK_ASSERT(ctx);
18986 NK_ASSERT(ctx->current);
18987 NK_ASSERT(ctx->current->layout);
18988 if (!ctx || !ctx->current || !ctx->current->layout)
18989 return;
18990
18991 /* spacing over row boundaries */
18992 win = ctx->current;
18993 layout = win->layout;
18994 index = (layout->row.index + cols) % layout->row.columns;
18995 rows = (layout->row.index + cols) / layout->row.columns;
18996 if (rows) {
18997 for (i = 0; i < rows; ++i)
18998 nk_panel_alloc_row(ctx, win);
18999 cols = index;
19000 }
19001 /* non table layout need to allocate space */
19002 if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
19003 layout->row.type != NK_LAYOUT_STATIC_FIXED) {
19004 for (i = 0; i < cols; ++i)
19005 nk_panel_alloc_space(&none, ctx);
19006 } layout->row.index = index;
19007}
19008
19009
19010
19011
19012/* ===============================================================
19013 *
19014 * TEXT
19015 *
19016 * ===============================================================*/
19017NK_LIB void
19018nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
19019 const char *string, int len, const struct nk_text *t,
19020 nk_flags a, const struct nk_user_font *f)
19021{
19022 struct nk_rect label;
19023 float text_width;
19024
19025 NK_ASSERT(o);
19026 NK_ASSERT(t);
19027 if (!o || !t) return;
19028
19029 b.h = NK_MAX(b.h, 2 * t->padding.y);
19030 label.x = 0; label.w = 0;
19031 label.y = b.y + t->padding.y;
19032 label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
19033
19034 text_width = f->width(f->userdata, f->height, (const char*)string, len);
19035 text_width += (2.0f * t->padding.x);
19036
19037 /* align in x-axis */
19038 if (a & NK_TEXT_ALIGN_LEFT) {
19039 label.x = b.x + t->padding.x;
19040 label.w = NK_MAX(0, b.w - 2 * t->padding.x);
19041 } else if (a & NK_TEXT_ALIGN_CENTERED) {
19042 label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
19043 label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
19044 label.x = NK_MAX(b.x + t->padding.x, label.x);
19045 label.w = NK_MIN(b.x + b.w, label.x + label.w);
19046 if (label.w >= label.x) label.w -= label.x;
19047 } else if (a & NK_TEXT_ALIGN_RIGHT) {
19048 label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
19049 label.w = (float)text_width + 2 * t->padding.x;
19050 } else return;
19051
19052 /* align in y-axis */
19053 if (a & NK_TEXT_ALIGN_MIDDLE) {
19054 label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
19055 label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
19056 } else if (a & NK_TEXT_ALIGN_BOTTOM) {
19057 label.y = b.y + b.h - f->height;
19058 label.h = f->height;
19059 }
19060 nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text);
19061}
19062NK_LIB void
19063nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
19064 const char *string, int len, const struct nk_text *t,
19065 const struct nk_user_font *f)
19066{
19067 float width;
19068 int glyphs = 0;
19069 int fitting = 0;
19070 int done = 0;
19071 struct nk_rect line;
19072 struct nk_text text;
19073 NK_INTERN nk_rune seperator[] = {' '};
19074
19075 NK_ASSERT(o);
19076 NK_ASSERT(t);
19077 if (!o || !t) return;
19078
19079 text.padding = nk_vec2(0,0);
19080 text.background = t->background;
19081 text.text = t->text;
19082
19083 b.w = NK_MAX(b.w, 2 * t->padding.x);
19084 b.h = NK_MAX(b.h, 2 * t->padding.y);
19085 b.h = b.h - 2 * t->padding.y;
19086
19087 line.x = b.x + t->padding.x;
19088 line.y = b.y + t->padding.y;
19089 line.w = b.w - 2 * t->padding.x;
19090 line.h = 2 * t->padding.y + f->height;
19091
19092 fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
19093 while (done < len) {
19094 if (!fitting || line.y + line.h >= (b.y + b.h)) break;
19095 nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
19096 done += fitting;
19097 line.y += f->height + 2 * t->padding.y;
19098 fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
19099 }
19100}
19101NK_API void
19102nk_text_colored(struct nk_context *ctx, const char *str, int len,
19103 nk_flags alignment, struct nk_color color)
19104{
19105 struct nk_window *win;
19106 const struct nk_style *style;
19107
19108 struct nk_vec2 item_padding;
19109 struct nk_rect bounds;
19110 struct nk_text text;
19111
19112 NK_ASSERT(ctx);
19113 NK_ASSERT(ctx->current);
19114 NK_ASSERT(ctx->current->layout);
19115 if (!ctx || !ctx->current || !ctx->current->layout) return;
19116
19117 win = ctx->current;
19118 style = &ctx->style;
19119 nk_panel_alloc_space(&bounds, ctx);
19120 item_padding = style->text.padding;
19121
19122 text.padding.x = item_padding.x;
19123 text.padding.y = item_padding.y;
19124 text.background = style->window.background;
19125 text.text = color;
19126 nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
19127}
19128NK_API void
19129nk_text_wrap_colored(struct nk_context *ctx, const char *str,
19130 int len, struct nk_color color)
19131{
19132 struct nk_window *win;
19133 const struct nk_style *style;
19134
19135 struct nk_vec2 item_padding;
19136 struct nk_rect bounds;
19137 struct nk_text text;
19138
19139 NK_ASSERT(ctx);
19140 NK_ASSERT(ctx->current);
19141 NK_ASSERT(ctx->current->layout);
19142 if (!ctx || !ctx->current || !ctx->current->layout) return;
19143
19144 win = ctx->current;
19145 style = &ctx->style;
19146 nk_panel_alloc_space(&bounds, ctx);
19147 item_padding = style->text.padding;
19148
19149 text.padding.x = item_padding.x;
19150 text.padding.y = item_padding.y;
19151 text.background = style->window.background;
19152 text.text = color;
19153 nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
19154}
19155#ifdef NK_INCLUDE_STANDARD_VARARGS
19156NK_API void
19157nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
19158 struct nk_color color, const char *fmt, ...)
19159{
19160 va_list args;
19161 va_start(args, fmt);
19162 nk_labelfv_colored(ctx, flags, color, fmt, args);
19163 va_end(args);
19164}
19165NK_API void
19166nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
19167 const char *fmt, ...)
19168{
19169 va_list args;
19170 va_start(args, fmt);
19171 nk_labelfv_colored_wrap(ctx, color, fmt, args);
19172 va_end(args);
19173}
19174NK_API void
19175nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
19176{
19177 va_list args;
19178 va_start(args, fmt);
19179 nk_labelfv(ctx, flags, fmt, args);
19180 va_end(args);
19181}
19182NK_API void
19183nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
19184{
19185 va_list args;
19186 va_start(args, fmt);
19187 nk_labelfv_wrap(ctx, fmt, args);
19188 va_end(args);
19189}
19190NK_API void
19191nk_labelfv_colored(struct nk_context *ctx, nk_flags flags,
19192 struct nk_color color, const char *fmt, va_list args)
19193{
19194 char buf[256];
19195 nk_strfmt(buf, NK_LEN(buf), fmt, args);
19196 nk_label_colored(ctx, buf, flags, color);
19197}
19198
19199NK_API void
19200nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color,
19201 const char *fmt, va_list args)
19202{
19203 char buf[256];
19204 nk_strfmt(buf, NK_LEN(buf), fmt, args);
19205 nk_label_colored_wrap(ctx, buf, color);
19206}
19207
19208NK_API void
19209nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args)
19210{
19211 char buf[256];
19212 nk_strfmt(buf, NK_LEN(buf), fmt, args);
19213 nk_label(ctx, buf, flags);
19214}
19215
19216NK_API void
19217nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args)
19218{
19219 char buf[256];
19220 nk_strfmt(buf, NK_LEN(buf), fmt, args);
19221 nk_label_wrap(ctx, buf);
19222}
19223
19224NK_API void
19225nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
19226{
19227 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));
19228}
19229NK_API void
19230nk_value_int(struct nk_context *ctx, const char *prefix, int value)
19231{
19232 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);
19233}
19234NK_API void
19235nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
19236{
19237 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);
19238}
19239NK_API void
19240nk_value_float(struct nk_context *ctx, const char *prefix, float value)
19241{
19242 double double_value = (double)value;
19243 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
19244}
19245NK_API void
19246nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
19247{
19248 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);
19249}
19250NK_API void
19251nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
19252{
19253 double c[4]; nk_color_dv(c, color);
19254 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
19255 p, c[0], c[1], c[2], c[3]);
19256}
19257NK_API void
19258nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
19259{
19260 char hex[16];
19261 nk_color_hex_rgba(hex, color);
19262 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
19263}
19264#endif
19265NK_API void
19266nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
19267{
19268 NK_ASSERT(ctx);
19269 if (!ctx) return;
19270 nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
19271}
19272NK_API void
19273nk_text_wrap(struct nk_context *ctx, const char *str, int len)
19274{
19275 NK_ASSERT(ctx);
19276 if (!ctx) return;
19277 nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
19278}
19279NK_API void
19280nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
19281{
19282 nk_text(ctx, str, nk_strlen(str), alignment);
19283}
19284NK_API void
19285nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
19286 struct nk_color color)
19287{
19288 nk_text_colored(ctx, str, nk_strlen(str), align, color);
19289}
19290NK_API void
19291nk_label_wrap(struct nk_context *ctx, const char *str)
19292{
19293 nk_text_wrap(ctx, str, nk_strlen(str));
19294}
19295NK_API void
19296nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
19297{
19298 nk_text_wrap_colored(ctx, str, nk_strlen(str), color);
19299}
19300
19301
19302
19303
19304/* ===============================================================
19305 *
19306 * IMAGE
19307 *
19308 * ===============================================================*/
19310nk_handle_ptr(void *ptr)
19311{
19312 nk_handle handle = {0};
19313 handle.ptr = ptr;
19314 return handle;
19315}
19317nk_handle_id(int id)
19318{
19319 nk_handle handle;
19320 nk_zero_struct(handle);
19321 handle.id = id;
19322 return handle;
19323}
19324NK_API struct nk_image
19325nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
19326{
19327 struct nk_image s;
19328 nk_zero(&s, sizeof(s));
19329 s.handle.ptr = ptr;
19330 s.w = w; s.h = h;
19331 s.region[0] = (unsigned short)r.x;
19332 s.region[1] = (unsigned short)r.y;
19333 s.region[2] = (unsigned short)r.w;
19334 s.region[3] = (unsigned short)r.h;
19335 return s;
19336}
19337NK_API struct nk_image
19338nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
19339{
19340 struct nk_image s;
19341 nk_zero(&s, sizeof(s));
19342 s.handle.id = id;
19343 s.w = w; s.h = h;
19344 s.region[0] = (unsigned short)r.x;
19345 s.region[1] = (unsigned short)r.y;
19346 s.region[2] = (unsigned short)r.w;
19347 s.region[3] = (unsigned short)r.h;
19348 return s;
19349}
19350NK_API struct nk_image
19351nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
19352 struct nk_rect r)
19353{
19354 struct nk_image s;
19355 nk_zero(&s, sizeof(s));
19356 s.handle = handle;
19357 s.w = w; s.h = h;
19358 s.region[0] = (unsigned short)r.x;
19359 s.region[1] = (unsigned short)r.y;
19360 s.region[2] = (unsigned short)r.w;
19361 s.region[3] = (unsigned short)r.h;
19362 return s;
19363}
19364NK_API struct nk_image
19366{
19367 struct nk_image s;
19368 nk_zero(&s, sizeof(s));
19369 s.handle = handle;
19370 s.w = 0; s.h = 0;
19371 s.region[0] = 0;
19372 s.region[1] = 0;
19373 s.region[2] = 0;
19374 s.region[3] = 0;
19375 return s;
19376}
19377NK_API struct nk_image
19378nk_image_ptr(void *ptr)
19379{
19380 struct nk_image s;
19381 nk_zero(&s, sizeof(s));
19382 NK_ASSERT(ptr);
19383 s.handle.ptr = ptr;
19384 s.w = 0; s.h = 0;
19385 s.region[0] = 0;
19386 s.region[1] = 0;
19387 s.region[2] = 0;
19388 s.region[3] = 0;
19389 return s;
19390}
19391NK_API struct nk_image
19392nk_image_id(int id)
19393{
19394 struct nk_image s;
19395 nk_zero(&s, sizeof(s));
19396 s.handle.id = id;
19397 s.w = 0; s.h = 0;
19398 s.region[0] = 0;
19399 s.region[1] = 0;
19400 s.region[2] = 0;
19401 s.region[3] = 0;
19402 return s;
19403}
19404NK_API int
19405nk_image_is_subimage(const struct nk_image* img)
19406{
19407 NK_ASSERT(img);
19408 return !(img->w == 0 && img->h == 0);
19409}
19410NK_API void
19411nk_image(struct nk_context *ctx, struct nk_image img)
19412{
19413 struct nk_window *win;
19414 struct nk_rect bounds;
19415
19416 NK_ASSERT(ctx);
19417 NK_ASSERT(ctx->current);
19418 NK_ASSERT(ctx->current->layout);
19419 if (!ctx || !ctx->current || !ctx->current->layout) return;
19420
19421 win = ctx->current;
19422 if (!nk_widget(&bounds, ctx)) return;
19423 nk_draw_image(&win->buffer, bounds, &img, nk_white);
19424}
19425NK_API void
19426nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col)
19427{
19428 struct nk_window *win;
19429 struct nk_rect bounds;
19430
19431 NK_ASSERT(ctx);
19432 NK_ASSERT(ctx->current);
19433 NK_ASSERT(ctx->current->layout);
19434 if (!ctx || !ctx->current || !ctx->current->layout) return;
19435
19436 win = ctx->current;
19437 if (!nk_widget(&bounds, ctx)) return;
19438 nk_draw_image(&win->buffer, bounds, &img, col);
19439}
19440
19441
19442
19443
19444/* ==============================================================
19445 *
19446 * BUTTON
19447 *
19448 * ===============================================================*/
19449NK_LIB void
19450nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
19451 struct nk_rect content, struct nk_color background, struct nk_color foreground,
19452 float border_width, const struct nk_user_font *font)
19453{
19454 switch (type) {
19455 case NK_SYMBOL_X:
19457 case NK_SYMBOL_PLUS:
19458 case NK_SYMBOL_MINUS: {
19459 /* single character text symbol */
19460 const char *X = (type == NK_SYMBOL_X) ? "x":
19461 (type == NK_SYMBOL_UNDERSCORE) ? "_":
19462 (type == NK_SYMBOL_PLUS) ? "+": "-";
19463 struct nk_text text;
19464 text.padding = nk_vec2(0,0);
19465 text.background = background;
19466 text.text = foreground;
19467 nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
19468 } break;
19473 /* simple empty/filled shapes */
19474 if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
19475 nk_fill_rect(out, content, 0, foreground);
19476 if (type == NK_SYMBOL_RECT_OUTLINE)
19477 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
19478 } else {
19479 nk_fill_circle(out, content, foreground);
19480 if (type == NK_SYMBOL_CIRCLE_OUTLINE)
19481 nk_fill_circle(out, nk_shrink_rect(content, 1), background);
19482 }
19483 } break;
19488 enum nk_heading heading;
19489 struct nk_vec2 points[3];
19490 heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
19491 (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
19492 (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
19493 nk_triangle_from_direction(points, content, 0, 0, heading);
19494 nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
19495 points[2].x, points[2].y, foreground);
19496 } break;
19497 default:
19498 case NK_SYMBOL_NONE:
19499 case NK_SYMBOL_MAX: break;
19500 }
19501}
19502NK_LIB int
19503nk_button_behavior(nk_flags *state, struct nk_rect r,
19504 const struct nk_input *i, enum nk_button_behavior behavior)
19505{
19506 int ret = 0;
19507 nk_widget_state_reset(state);
19508 if (!i) return 0;
19510 *state = NK_WIDGET_STATE_HOVERED;
19512 *state = NK_WIDGET_STATE_ACTIVE;
19514 ret = (behavior != NK_BUTTON_DEFAULT) ?
19516#ifdef NK_BUTTON_TRIGGER_ON_RELEASE
19518#else
19520#endif
19521 }
19522 }
19524 *state |= NK_WIDGET_STATE_ENTERED;
19526 *state |= NK_WIDGET_STATE_LEFT;
19527 return ret;
19528}
19529NK_LIB const struct nk_style_item*
19530nk_draw_button(struct nk_command_buffer *out,
19531 const struct nk_rect *bounds, nk_flags state,
19532 const struct nk_style_button *style)
19533{
19534 const struct nk_style_item *background;
19535 if (state & NK_WIDGET_STATE_HOVER)
19536 background = &style->hover;
19537 else if (state & NK_WIDGET_STATE_ACTIVED)
19538 background = &style->active;
19539 else background = &style->normal;
19540
19541 if (background->type == NK_STYLE_ITEM_IMAGE) {
19542 nk_draw_image(out, *bounds, &background->data.image, nk_white);
19543 } else {
19544 nk_fill_rect(out, *bounds, style->rounding, background->data.color);
19545 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
19546 }
19547 return background;
19548}
19549NK_LIB int
19550nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
19551 const struct nk_style_button *style, const struct nk_input *in,
19552 enum nk_button_behavior behavior, struct nk_rect *content)
19553{
19554 struct nk_rect bounds;
19555 NK_ASSERT(style);
19556 NK_ASSERT(state);
19557 NK_ASSERT(out);
19558 if (!out || !style)
19559 return nk_false;
19560
19561 /* calculate button content space */
19562 content->x = r.x + style->padding.x + style->border + style->rounding;
19563 content->y = r.y + style->padding.y + style->border + style->rounding;
19564 content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
19565 content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
19566
19567 /* execute button behavior */
19568 bounds.x = r.x - style->touch_padding.x;
19569 bounds.y = r.y - style->touch_padding.y;
19570 bounds.w = r.w + 2 * style->touch_padding.x;
19571 bounds.h = r.h + 2 * style->touch_padding.y;
19572 return nk_button_behavior(state, bounds, in, behavior);
19573}
19574NK_LIB void
19575nk_draw_button_text(struct nk_command_buffer *out,
19576 const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
19577 const struct nk_style_button *style, const char *txt, int len,
19578 nk_flags text_alignment, const struct nk_user_font *font)
19579{
19580 struct nk_text text;
19581 const struct nk_style_item *background;
19582 background = nk_draw_button(out, bounds, state, style);
19583
19584 /* select correct colors/images */
19585 if (background->type == NK_STYLE_ITEM_COLOR)
19586 text.background = background->data.color;
19587 else text.background = style->text_background;
19588 if (state & NK_WIDGET_STATE_HOVER)
19589 text.text = style->text_hover;
19590 else if (state & NK_WIDGET_STATE_ACTIVED)
19591 text.text = style->text_active;
19592 else text.text = style->text_normal;
19593
19594 text.padding = nk_vec2(0,0);
19595 nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
19596}
19597NK_LIB int
19598nk_do_button_text(nk_flags *state,
19599 struct nk_command_buffer *out, struct nk_rect bounds,
19600 const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
19601 const struct nk_style_button *style, const struct nk_input *in,
19602 const struct nk_user_font *font)
19603{
19604 struct nk_rect content;
19605 int ret = nk_false;
19606
19607 NK_ASSERT(state);
19608 NK_ASSERT(style);
19609 NK_ASSERT(out);
19610 NK_ASSERT(string);
19611 NK_ASSERT(font);
19612 if (!out || !style || !font || !string)
19613 return nk_false;
19614
19615 ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19616 if (style->draw_begin) style->draw_begin(out, style->userdata);
19617 nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
19618 if (style->draw_end) style->draw_end(out, style->userdata);
19619 return ret;
19620}
19621NK_LIB void
19622nk_draw_button_symbol(struct nk_command_buffer *out,
19623 const struct nk_rect *bounds, const struct nk_rect *content,
19624 nk_flags state, const struct nk_style_button *style,
19625 enum nk_symbol_type type, const struct nk_user_font *font)
19626{
19627 struct nk_color sym, bg;
19628 const struct nk_style_item *background;
19629
19630 /* select correct colors/images */
19631 background = nk_draw_button(out, bounds, state, style);
19632 if (background->type == NK_STYLE_ITEM_COLOR)
19633 bg = background->data.color;
19634 else bg = style->text_background;
19635
19636 if (state & NK_WIDGET_STATE_HOVER)
19637 sym = style->text_hover;
19638 else if (state & NK_WIDGET_STATE_ACTIVED)
19639 sym = style->text_active;
19640 else sym = style->text_normal;
19641 nk_draw_symbol(out, type, *content, bg, sym, 1, font);
19642}
19643NK_LIB int
19644nk_do_button_symbol(nk_flags *state,
19645 struct nk_command_buffer *out, struct nk_rect bounds,
19646 enum nk_symbol_type symbol, enum nk_button_behavior behavior,
19647 const struct nk_style_button *style, const struct nk_input *in,
19648 const struct nk_user_font *font)
19649{
19650 int ret;
19651 struct nk_rect content;
19652
19653 NK_ASSERT(state);
19654 NK_ASSERT(style);
19655 NK_ASSERT(font);
19656 NK_ASSERT(out);
19657 if (!out || !style || !font || !state)
19658 return nk_false;
19659
19660 ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19661 if (style->draw_begin) style->draw_begin(out, style->userdata);
19662 nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
19663 if (style->draw_end) style->draw_end(out, style->userdata);
19664 return ret;
19665}
19666NK_LIB void
19667nk_draw_button_image(struct nk_command_buffer *out,
19668 const struct nk_rect *bounds, const struct nk_rect *content,
19669 nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
19670{
19671 nk_draw_button(out, bounds, state, style);
19672 nk_draw_image(out, *content, img, nk_white);
19673}
19674NK_LIB int
19675nk_do_button_image(nk_flags *state,
19676 struct nk_command_buffer *out, struct nk_rect bounds,
19677 struct nk_image img, enum nk_button_behavior b,
19678 const struct nk_style_button *style, const struct nk_input *in)
19679{
19680 int ret;
19681 struct nk_rect content;
19682
19683 NK_ASSERT(state);
19684 NK_ASSERT(style);
19685 NK_ASSERT(out);
19686 if (!out || !style || !state)
19687 return nk_false;
19688
19689 ret = nk_do_button(state, out, bounds, style, in, b, &content);
19690 content.x += style->image_padding.x;
19691 content.y += style->image_padding.y;
19692 content.w -= 2 * style->image_padding.x;
19693 content.h -= 2 * style->image_padding.y;
19694
19695 if (style->draw_begin) style->draw_begin(out, style->userdata);
19696 nk_draw_button_image(out, &bounds, &content, *state, style, &img);
19697 if (style->draw_end) style->draw_end(out, style->userdata);
19698 return ret;
19699}
19700NK_LIB void
19701nk_draw_button_text_symbol(struct nk_command_buffer *out,
19702 const struct nk_rect *bounds, const struct nk_rect *label,
19703 const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
19704 const char *str, int len, enum nk_symbol_type type,
19705 const struct nk_user_font *font)
19706{
19707 struct nk_color sym;
19708 struct nk_text text;
19709 const struct nk_style_item *background;
19710
19711 /* select correct background colors/images */
19712 background = nk_draw_button(out, bounds, state, style);
19713 if (background->type == NK_STYLE_ITEM_COLOR)
19714 text.background = background->data.color;
19715 else text.background = style->text_background;
19716
19717 /* select correct text colors */
19718 if (state & NK_WIDGET_STATE_HOVER) {
19719 sym = style->text_hover;
19720 text.text = style->text_hover;
19721 } else if (state & NK_WIDGET_STATE_ACTIVED) {
19722 sym = style->text_active;
19723 text.text = style->text_active;
19724 } else {
19725 sym = style->text_normal;
19726 text.text = style->text_normal;
19727 }
19728
19729 text.padding = nk_vec2(0,0);
19730 nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
19731 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
19732}
19733NK_LIB int
19734nk_do_button_text_symbol(nk_flags *state,
19735 struct nk_command_buffer *out, struct nk_rect bounds,
19736 enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
19737 enum nk_button_behavior behavior, const struct nk_style_button *style,
19738 const struct nk_user_font *font, const struct nk_input *in)
19739{
19740 int ret;
19741 struct nk_rect tri = {0,0,0,0};
19742 struct nk_rect content;
19743
19744 NK_ASSERT(style);
19745 NK_ASSERT(out);
19746 NK_ASSERT(font);
19747 if (!out || !style || !font)
19748 return nk_false;
19749
19750 ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19751 tri.y = content.y + (content.h/2) - font->height/2;
19752 tri.w = font->height; tri.h = font->height;
19753 if (align & NK_TEXT_ALIGN_LEFT) {
19754 tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
19755 tri.x = NK_MAX(tri.x, 0);
19756 } else tri.x = content.x + 2 * style->padding.x;
19757
19758 /* draw button */
19759 if (style->draw_begin) style->draw_begin(out, style->userdata);
19760 nk_draw_button_text_symbol(out, &bounds, &content, &tri,
19761 *state, style, str, len, symbol, font);
19762 if (style->draw_end) style->draw_end(out, style->userdata);
19763 return ret;
19764}
19765NK_LIB void
19766nk_draw_button_text_image(struct nk_command_buffer *out,
19767 const struct nk_rect *bounds, const struct nk_rect *label,
19768 const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
19769 const char *str, int len, const struct nk_user_font *font,
19770 const struct nk_image *img)
19771{
19772 struct nk_text text;
19773 const struct nk_style_item *background;
19774 background = nk_draw_button(out, bounds, state, style);
19775
19776 /* select correct colors */
19777 if (background->type == NK_STYLE_ITEM_COLOR)
19778 text.background = background->data.color;
19779 else text.background = style->text_background;
19780 if (state & NK_WIDGET_STATE_HOVER)
19781 text.text = style->text_hover;
19782 else if (state & NK_WIDGET_STATE_ACTIVED)
19783 text.text = style->text_active;
19784 else text.text = style->text_normal;
19785
19786 text.padding = nk_vec2(0,0);
19787 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
19788 nk_draw_image(out, *image, img, nk_white);
19789}
19790NK_LIB int
19791nk_do_button_text_image(nk_flags *state,
19792 struct nk_command_buffer *out, struct nk_rect bounds,
19793 struct nk_image img, const char* str, int len, nk_flags align,
19794 enum nk_button_behavior behavior, const struct nk_style_button *style,
19795 const struct nk_user_font *font, const struct nk_input *in)
19796{
19797 int ret;
19798 struct nk_rect icon;
19799 struct nk_rect content;
19800
19801 NK_ASSERT(style);
19802 NK_ASSERT(state);
19803 NK_ASSERT(font);
19804 NK_ASSERT(out);
19805 if (!out || !font || !style || !str)
19806 return nk_false;
19807
19808 ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19809 icon.y = bounds.y + style->padding.y;
19810 icon.w = icon.h = bounds.h - 2 * style->padding.y;
19811 if (align & NK_TEXT_ALIGN_LEFT) {
19812 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
19813 icon.x = NK_MAX(icon.x, 0);
19814 } else icon.x = bounds.x + 2 * style->padding.x;
19815
19816 icon.x += style->image_padding.x;
19817 icon.y += style->image_padding.y;
19818 icon.w -= 2 * style->image_padding.x;
19819 icon.h -= 2 * style->image_padding.y;
19820
19821 if (style->draw_begin) style->draw_begin(out, style->userdata);
19822 nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
19823 if (style->draw_end) style->draw_end(out, style->userdata);
19824 return ret;
19825}
19826NK_API void
19827nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
19828{
19829 NK_ASSERT(ctx);
19830 if (!ctx) return;
19831 ctx->button_behavior = behavior;
19832}
19833NK_API int
19834nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
19835{
19836 struct nk_config_stack_button_behavior *button_stack;
19837 struct nk_config_stack_button_behavior_element *element;
19838
19839 NK_ASSERT(ctx);
19840 if (!ctx) return 0;
19841
19842 button_stack = &ctx->stacks.button_behaviors;
19843 NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
19844 if (button_stack->head >= (int)NK_LEN(button_stack->elements))
19845 return 0;
19846
19847 element = &button_stack->elements[button_stack->head++];
19848 element->address = &ctx->button_behavior;
19849 element->old_value = ctx->button_behavior;
19850 ctx->button_behavior = behavior;
19851 return 1;
19852}
19853NK_API int
19855{
19856 struct nk_config_stack_button_behavior *button_stack;
19857 struct nk_config_stack_button_behavior_element *element;
19858
19859 NK_ASSERT(ctx);
19860 if (!ctx) return 0;
19861
19862 button_stack = &ctx->stacks.button_behaviors;
19863 NK_ASSERT(button_stack->head > 0);
19864 if (button_stack->head < 1)
19865 return 0;
19866
19867 element = &button_stack->elements[--button_stack->head];
19868 *element->address = element->old_value;
19869 return 1;
19870}
19871NK_API int
19873 const struct nk_style_button *style, const char *title, int len)
19874{
19875 struct nk_window *win;
19876 struct nk_panel *layout;
19877 const struct nk_input *in;
19878
19879 struct nk_rect bounds;
19880 enum nk_widget_layout_states state;
19881
19882 NK_ASSERT(ctx);
19883 NK_ASSERT(style);
19884 NK_ASSERT(ctx->current);
19885 NK_ASSERT(ctx->current->layout);
19886 if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
19887
19888 win = ctx->current;
19889 layout = win->layout;
19890 state = nk_widget(&bounds, ctx);
19891
19892 if (!state) return 0;
19893 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
19894 return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
19895 title, len, style->text_alignment, ctx->button_behavior,
19896 style, in, ctx->style.font);
19897}
19898NK_API int
19899nk_button_text(struct nk_context *ctx, const char *title, int len)
19900{
19901 NK_ASSERT(ctx);
19902 if (!ctx) return 0;
19903 return nk_button_text_styled(ctx, &ctx->style.button, title, len);
19904}
19906 const struct nk_style_button *style, const char *title)
19907{
19908 return nk_button_text_styled(ctx, style, title, nk_strlen(title));
19909}
19910NK_API int nk_button_label(struct nk_context *ctx, const char *title)
19911{
19912 return nk_button_text(ctx, title, nk_strlen(title));
19913}
19914NK_API int
19915nk_button_color(struct nk_context *ctx, struct nk_color color)
19916{
19917 struct nk_window *win;
19918 struct nk_panel *layout;
19919 const struct nk_input *in;
19920 struct nk_style_button button;
19921
19922 int ret = 0;
19923 struct nk_rect bounds;
19924 struct nk_rect content;
19925 enum nk_widget_layout_states state;
19926
19927 NK_ASSERT(ctx);
19928 NK_ASSERT(ctx->current);
19929 NK_ASSERT(ctx->current->layout);
19930 if (!ctx || !ctx->current || !ctx->current->layout)
19931 return 0;
19932
19933 win = ctx->current;
19934 layout = win->layout;
19935
19936 state = nk_widget(&bounds, ctx);
19937 if (!state) return 0;
19938 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
19939
19940 button = ctx->style.button;
19941 button.normal = nk_style_item_color(color);
19942 button.hover = nk_style_item_color(color);
19943 button.active = nk_style_item_color(color);
19944 ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
19945 &button, in, ctx->button_behavior, &content);
19946 nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
19947 return ret;
19948}
19949NK_API int
19951 const struct nk_style_button *style, enum nk_symbol_type symbol)
19952{
19953 struct nk_window *win;
19954 struct nk_panel *layout;
19955 const struct nk_input *in;
19956
19957 struct nk_rect bounds;
19958 enum nk_widget_layout_states state;
19959
19960 NK_ASSERT(ctx);
19961 NK_ASSERT(ctx->current);
19962 NK_ASSERT(ctx->current->layout);
19963 if (!ctx || !ctx->current || !ctx->current->layout)
19964 return 0;
19965
19966 win = ctx->current;
19967 layout = win->layout;
19968 state = nk_widget(&bounds, ctx);
19969 if (!state) return 0;
19970 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
19971 return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
19972 symbol, ctx->button_behavior, style, in, ctx->style.font);
19973}
19974NK_API int
19975nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
19976{
19977 NK_ASSERT(ctx);
19978 if (!ctx) return 0;
19979 return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
19980}
19981NK_API int
19982nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
19983 struct nk_image img)
19984{
19985 struct nk_window *win;
19986 struct nk_panel *layout;
19987 const struct nk_input *in;
19988
19989 struct nk_rect bounds;
19990 enum nk_widget_layout_states state;
19991
19992 NK_ASSERT(ctx);
19993 NK_ASSERT(ctx->current);
19994 NK_ASSERT(ctx->current->layout);
19995 if (!ctx || !ctx->current || !ctx->current->layout)
19996 return 0;
19997
19998 win = ctx->current;
19999 layout = win->layout;
20000
20001 state = nk_widget(&bounds, ctx);
20002 if (!state) return 0;
20003 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20004 return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
20005 img, ctx->button_behavior, style, in);
20006}
20007NK_API int
20008nk_button_image(struct nk_context *ctx, struct nk_image img)
20009{
20010 NK_ASSERT(ctx);
20011 if (!ctx) return 0;
20012 return nk_button_image_styled(ctx, &ctx->style.button, img);
20013}
20014NK_API int
20016 const struct nk_style_button *style, enum nk_symbol_type symbol,
20017 const char *text, int len, nk_flags align)
20018{
20019 struct nk_window *win;
20020 struct nk_panel *layout;
20021 const struct nk_input *in;
20022
20023 struct nk_rect bounds;
20024 enum nk_widget_layout_states state;
20025
20026 NK_ASSERT(ctx);
20027 NK_ASSERT(ctx->current);
20028 NK_ASSERT(ctx->current->layout);
20029 if (!ctx || !ctx->current || !ctx->current->layout)
20030 return 0;
20031
20032 win = ctx->current;
20033 layout = win->layout;
20034
20035 state = nk_widget(&bounds, ctx);
20036 if (!state) return 0;
20037 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20038 return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20039 symbol, text, len, align, ctx->button_behavior,
20040 style, ctx->style.font, in);
20041}
20042NK_API int
20043nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
20044 const char* text, int len, nk_flags align)
20045{
20046 NK_ASSERT(ctx);
20047 if (!ctx) return 0;
20048 return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
20049}
20050NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
20051 const char *label, nk_flags align)
20052{
20053 return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);
20054}
20056 const struct nk_style_button *style, enum nk_symbol_type symbol,
20057 const char *title, nk_flags align)
20058{
20059 return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);
20060}
20061NK_API int
20063 const struct nk_style_button *style, struct nk_image img, const char *text,
20064 int len, nk_flags align)
20065{
20066 struct nk_window *win;
20067 struct nk_panel *layout;
20068 const struct nk_input *in;
20069
20070 struct nk_rect bounds;
20071 enum nk_widget_layout_states state;
20072
20073 NK_ASSERT(ctx);
20074 NK_ASSERT(ctx->current);
20075 NK_ASSERT(ctx->current->layout);
20076 if (!ctx || !ctx->current || !ctx->current->layout)
20077 return 0;
20078
20079 win = ctx->current;
20080 layout = win->layout;
20081
20082 state = nk_widget(&bounds, ctx);
20083 if (!state) return 0;
20084 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20085 return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
20086 bounds, img, text, len, align, ctx->button_behavior,
20087 style, ctx->style.font, in);
20088}
20089NK_API int
20090nk_button_image_text(struct nk_context *ctx, struct nk_image img,
20091 const char *text, int len, nk_flags align)
20092{
20093 return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);
20094}
20095NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img,
20096 const char *label, nk_flags align)
20097{
20098 return nk_button_image_text(ctx, img, label, nk_strlen(label), align);
20099}
20101 const struct nk_style_button *style, struct nk_image img,
20102 const char *label, nk_flags text_alignment)
20103{
20104 return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);
20105}
20106
20107
20108
20109
20110/* ===============================================================
20111 *
20112 * TOGGLE
20113 *
20114 * ===============================================================*/
20115NK_LIB int
20116nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
20117 nk_flags *state, int active)
20118{
20119 nk_widget_state_reset(state);
20120 if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
20121 *state = NK_WIDGET_STATE_ACTIVE;
20122 active = !active;
20123 }
20125 *state |= NK_WIDGET_STATE_ENTERED;
20126 else if (nk_input_is_mouse_prev_hovering_rect(in, select))
20127 *state |= NK_WIDGET_STATE_LEFT;
20128 return active;
20129}
20130NK_LIB void
20131nk_draw_checkbox(struct nk_command_buffer *out,
20132 nk_flags state, const struct nk_style_toggle *style, int active,
20133 const struct nk_rect *label, const struct nk_rect *selector,
20134 const struct nk_rect *cursors, const char *string, int len,
20135 const struct nk_user_font *font)
20136{
20137 const struct nk_style_item *background;
20138 const struct nk_style_item *cursor;
20139 struct nk_text text;
20140
20141 /* select correct colors/images */
20142 if (state & NK_WIDGET_STATE_HOVER) {
20143 background = &style->hover;
20144 cursor = &style->cursor_hover;
20145 text.text = style->text_hover;
20146 } else if (state & NK_WIDGET_STATE_ACTIVED) {
20147 background = &style->hover;
20148 cursor = &style->cursor_hover;
20149 text.text = style->text_active;
20150 } else {
20151 background = &style->normal;
20152 cursor = &style->cursor_normal;
20153 text.text = style->text_normal;
20154 }
20155
20156 /* draw background and cursor */
20157 if (background->type == NK_STYLE_ITEM_COLOR) {
20158 nk_fill_rect(out, *selector, 0, style->border_color);
20159 nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
20160 } else nk_draw_image(out, *selector, &background->data.image, nk_white);
20161 if (active) {
20162 if (cursor->type == NK_STYLE_ITEM_IMAGE)
20163 nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
20164 else nk_fill_rect(out, *cursors, 0, cursor->data.color);
20165 }
20166
20167 text.padding.x = 0;
20168 text.padding.y = 0;
20169 text.background = style->text_background;
20170 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
20171}
20172NK_LIB void
20173nk_draw_option(struct nk_command_buffer *out,
20174 nk_flags state, const struct nk_style_toggle *style, int active,
20175 const struct nk_rect *label, const struct nk_rect *selector,
20176 const struct nk_rect *cursors, const char *string, int len,
20177 const struct nk_user_font *font)
20178{
20179 const struct nk_style_item *background;
20180 const struct nk_style_item *cursor;
20181 struct nk_text text;
20182
20183 /* select correct colors/images */
20184 if (state & NK_WIDGET_STATE_HOVER) {
20185 background = &style->hover;
20186 cursor = &style->cursor_hover;
20187 text.text = style->text_hover;
20188 } else if (state & NK_WIDGET_STATE_ACTIVED) {
20189 background = &style->hover;
20190 cursor = &style->cursor_hover;
20191 text.text = style->text_active;
20192 } else {
20193 background = &style->normal;
20194 cursor = &style->cursor_normal;
20195 text.text = style->text_normal;
20196 }
20197
20198 /* draw background and cursor */
20199 if (background->type == NK_STYLE_ITEM_COLOR) {
20200 nk_fill_circle(out, *selector, style->border_color);
20201 nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
20202 } else nk_draw_image(out, *selector, &background->data.image, nk_white);
20203 if (active) {
20204 if (cursor->type == NK_STYLE_ITEM_IMAGE)
20205 nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
20206 else nk_fill_circle(out, *cursors, cursor->data.color);
20207 }
20208
20209 text.padding.x = 0;
20210 text.padding.y = 0;
20211 text.background = style->text_background;
20212 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
20213}
20214NK_LIB int
20215nk_do_toggle(nk_flags *state,
20216 struct nk_command_buffer *out, struct nk_rect r,
20217 int *active, const char *str, int len, enum nk_toggle_type type,
20218 const struct nk_style_toggle *style, const struct nk_input *in,
20219 const struct nk_user_font *font)
20220{
20221 int was_active;
20222 struct nk_rect bounds;
20223 struct nk_rect select;
20224 struct nk_rect cursor;
20225 struct nk_rect label;
20226
20227 NK_ASSERT(style);
20228 NK_ASSERT(out);
20229 NK_ASSERT(font);
20230 if (!out || !style || !font || !active)
20231 return 0;
20232
20233 r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
20234 r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
20235
20236 /* add additional touch padding for touch screen devices */
20237 bounds.x = r.x - style->touch_padding.x;
20238 bounds.y = r.y - style->touch_padding.y;
20239 bounds.w = r.w + 2 * style->touch_padding.x;
20240 bounds.h = r.h + 2 * style->touch_padding.y;
20241
20242 /* calculate the selector space */
20243 select.w = font->height;
20244 select.h = select.w;
20245 select.y = r.y + r.h/2.0f - select.h/2.0f;
20246 select.x = r.x;
20247
20248 /* calculate the bounds of the cursor inside the selector */
20249 cursor.x = select.x + style->padding.x + style->border;
20250 cursor.y = select.y + style->padding.y + style->border;
20251 cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
20252 cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
20253
20254 /* label behind the selector */
20255 label.x = select.x + select.w + style->spacing;
20256 label.y = select.y;
20257 label.w = NK_MAX(r.x + r.w, label.x) - label.x;
20258 label.h = select.w;
20259
20260 /* update selector */
20261 was_active = *active;
20262 *active = nk_toggle_behavior(in, bounds, state, *active);
20263
20264 /* draw selector */
20265 if (style->draw_begin)
20266 style->draw_begin(out, style->userdata);
20267 if (type == NK_TOGGLE_CHECK) {
20268 nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
20269 } else {
20270 nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
20271 }
20272 if (style->draw_end)
20273 style->draw_end(out, style->userdata);
20274 return (was_active != *active);
20275}
20276/*----------------------------------------------------------------
20277 *
20278 * CHECKBOX
20279 *
20280 * --------------------------------------------------------------*/
20281NK_API int
20282nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
20283{
20284 struct nk_window *win;
20285 struct nk_panel *layout;
20286 const struct nk_input *in;
20287 const struct nk_style *style;
20288
20289 struct nk_rect bounds;
20290 enum nk_widget_layout_states state;
20291
20292 NK_ASSERT(ctx);
20293 NK_ASSERT(ctx->current);
20294 NK_ASSERT(ctx->current->layout);
20295 if (!ctx || !ctx->current || !ctx->current->layout)
20296 return active;
20297
20298 win = ctx->current;
20299 style = &ctx->style;
20300 layout = win->layout;
20301
20302 state = nk_widget(&bounds, ctx);
20303 if (!state) return active;
20304 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20305 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
20306 text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
20307 return active;
20308}
20309NK_API unsigned int
20310nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
20311 unsigned int flags, unsigned int value)
20312{
20313 int old_active;
20314 NK_ASSERT(ctx);
20315 NK_ASSERT(text);
20316 if (!ctx || !text) return flags;
20317 old_active = (int)((flags & value) & value);
20318 if (nk_check_text(ctx, text, len, old_active))
20319 flags |= value;
20320 else flags &= ~value;
20321 return flags;
20322}
20323NK_API int
20324nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
20325{
20326 int old_val;
20327 NK_ASSERT(ctx);
20328 NK_ASSERT(text);
20329 NK_ASSERT(active);
20330 if (!ctx || !text || !active) return 0;
20331 old_val = *active;
20332 *active = nk_check_text(ctx, text, len, *active);
20333 return old_val != *active;
20334}
20335NK_API int
20336nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
20337 unsigned int *flags, unsigned int value)
20338{
20339 int active;
20340 NK_ASSERT(ctx);
20341 NK_ASSERT(text);
20342 NK_ASSERT(flags);
20343 if (!ctx || !text || !flags) return 0;
20344
20345 active = (int)((*flags & value) & value);
20346 if (nk_checkbox_text(ctx, text, len, &active)) {
20347 if (active) *flags |= value;
20348 else *flags &= ~value;
20349 return 1;
20350 }
20351 return 0;
20352}
20353NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
20354{
20355 return nk_check_text(ctx, label, nk_strlen(label), active);
20356}
20357NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
20358 unsigned int flags, unsigned int value)
20359{
20360 return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);
20361}
20362NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
20363{
20364 return nk_checkbox_text(ctx, label, nk_strlen(label), active);
20365}
20366NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
20367 unsigned int *flags, unsigned int value)
20368{
20369 return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);
20370}
20371/*----------------------------------------------------------------
20372 *
20373 * OPTION
20374 *
20375 * --------------------------------------------------------------*/
20376NK_API int
20377nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
20378{
20379 struct nk_window *win;
20380 struct nk_panel *layout;
20381 const struct nk_input *in;
20382 const struct nk_style *style;
20383
20384 struct nk_rect bounds;
20385 enum nk_widget_layout_states state;
20386
20387 NK_ASSERT(ctx);
20388 NK_ASSERT(ctx->current);
20389 NK_ASSERT(ctx->current->layout);
20390 if (!ctx || !ctx->current || !ctx->current->layout)
20391 return is_active;
20392
20393 win = ctx->current;
20394 style = &ctx->style;
20395 layout = win->layout;
20396
20397 state = nk_widget(&bounds, ctx);
20398 if (!state) return (int)state;
20399 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20400 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
20401 text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
20402 return is_active;
20403}
20404NK_API int
20405nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
20406{
20407 int old_value;
20408 NK_ASSERT(ctx);
20409 NK_ASSERT(text);
20410 NK_ASSERT(active);
20411 if (!ctx || !text || !active) return 0;
20412 old_value = *active;
20413 *active = nk_option_text(ctx, text, len, old_value);
20414 return old_value != *active;
20415}
20416NK_API int
20417nk_option_label(struct nk_context *ctx, const char *label, int active)
20418{
20419 return nk_option_text(ctx, label, nk_strlen(label), active);
20420}
20421NK_API int
20422nk_radio_label(struct nk_context *ctx, const char *label, int *active)
20423{
20424 return nk_radio_text(ctx, label, nk_strlen(label), active);
20425}
20426
20427
20428
20429
20430/* ===============================================================
20431 *
20432 * SELECTABLE
20433 *
20434 * ===============================================================*/
20435NK_LIB void
20436nk_draw_selectable(struct nk_command_buffer *out,
20437 nk_flags state, const struct nk_style_selectable *style, int active,
20438 const struct nk_rect *bounds,
20439 const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym,
20440 const char *string, int len, nk_flags align, const struct nk_user_font *font)
20441{
20442 const struct nk_style_item *background;
20443 struct nk_text text;
20444 text.padding = style->padding;
20445
20446 /* select correct colors/images */
20447 if (!active) {
20448 if (state & NK_WIDGET_STATE_ACTIVED) {
20449 background = &style->pressed;
20450 text.text = style->text_pressed;
20451 } else if (state & NK_WIDGET_STATE_HOVER) {
20452 background = &style->hover;
20453 text.text = style->text_hover;
20454 } else {
20455 background = &style->normal;
20456 text.text = style->text_normal;
20457 }
20458 } else {
20459 if (state & NK_WIDGET_STATE_ACTIVED) {
20460 background = &style->pressed_active;
20461 text.text = style->text_pressed_active;
20462 } else if (state & NK_WIDGET_STATE_HOVER) {
20463 background = &style->hover_active;
20464 text.text = style->text_hover_active;
20465 } else {
20466 background = &style->normal_active;
20467 text.text = style->text_normal_active;
20468 }
20469 }
20470 /* draw selectable background and text */
20471 if (background->type == NK_STYLE_ITEM_IMAGE) {
20472 nk_draw_image(out, *bounds, &background->data.image, nk_white);
20473 text.background = nk_rgba(0,0,0,0);
20474 } else {
20475 nk_fill_rect(out, *bounds, style->rounding, background->data.color);
20476 text.background = background->data.color;
20477 }
20478 if (icon) {
20479 if (img) nk_draw_image(out, *icon, img, nk_white);
20480 else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font);
20481 }
20482 nk_widget_text(out, *bounds, string, len, &text, align, font);
20483}
20484NK_LIB int
20485nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
20486 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
20487 const struct nk_style_selectable *style, const struct nk_input *in,
20488 const struct nk_user_font *font)
20489{
20490 int old_value;
20491 struct nk_rect touch;
20492
20493 NK_ASSERT(state);
20494 NK_ASSERT(out);
20495 NK_ASSERT(str);
20496 NK_ASSERT(len);
20497 NK_ASSERT(value);
20498 NK_ASSERT(style);
20499 NK_ASSERT(font);
20500
20501 if (!state || !out || !str || !len || !value || !style || !font) return 0;
20502 old_value = *value;
20503
20504 /* remove padding */
20505 touch.x = bounds.x - style->touch_padding.x;
20506 touch.y = bounds.y - style->touch_padding.y;
20507 touch.w = bounds.w + style->touch_padding.x * 2;
20508 touch.h = bounds.h + style->touch_padding.y * 2;
20509
20510 /* update button */
20511 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
20512 *value = !(*value);
20513
20514 /* draw selectable */
20515 if (style->draw_begin) style->draw_begin(out, style->userdata);
20516 nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font);
20517 if (style->draw_end) style->draw_end(out, style->userdata);
20518 return old_value != *value;
20519}
20520NK_LIB int
20521nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
20522 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
20523 const struct nk_image *img, const struct nk_style_selectable *style,
20524 const struct nk_input *in, const struct nk_user_font *font)
20525{
20526 int old_value;
20527 struct nk_rect touch;
20528 struct nk_rect icon;
20529
20530 NK_ASSERT(state);
20531 NK_ASSERT(out);
20532 NK_ASSERT(str);
20533 NK_ASSERT(len);
20534 NK_ASSERT(value);
20535 NK_ASSERT(style);
20536 NK_ASSERT(font);
20537
20538 if (!state || !out || !str || !len || !value || !style || !font) return 0;
20539 old_value = *value;
20540
20541 /* toggle behavior */
20542 touch.x = bounds.x - style->touch_padding.x;
20543 touch.y = bounds.y - style->touch_padding.y;
20544 touch.w = bounds.w + style->touch_padding.x * 2;
20545 touch.h = bounds.h + style->touch_padding.y * 2;
20546 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
20547 *value = !(*value);
20548
20549 icon.y = bounds.y + style->padding.y;
20550 icon.w = icon.h = bounds.h - 2 * style->padding.y;
20551 if (align & NK_TEXT_ALIGN_LEFT) {
20552 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
20553 icon.x = NK_MAX(icon.x, 0);
20554 } else icon.x = bounds.x + 2 * style->padding.x;
20555
20556 icon.x += style->image_padding.x;
20557 icon.y += style->image_padding.y;
20558 icon.w -= 2 * style->image_padding.x;
20559 icon.h -= 2 * style->image_padding.y;
20560
20561 /* draw selectable */
20562 if (style->draw_begin) style->draw_begin(out, style->userdata);
20563 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font);
20564 if (style->draw_end) style->draw_end(out, style->userdata);
20565 return old_value != *value;
20566}
20567NK_LIB int
20568nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out,
20569 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
20570 enum nk_symbol_type sym, const struct nk_style_selectable *style,
20571 const struct nk_input *in, const struct nk_user_font *font)
20572{
20573 int old_value;
20574 struct nk_rect touch;
20575 struct nk_rect icon;
20576
20577 NK_ASSERT(state);
20578 NK_ASSERT(out);
20579 NK_ASSERT(str);
20580 NK_ASSERT(len);
20581 NK_ASSERT(value);
20582 NK_ASSERT(style);
20583 NK_ASSERT(font);
20584
20585 if (!state || !out || !str || !len || !value || !style || !font) return 0;
20586 old_value = *value;
20587
20588 /* toggle behavior */
20589 touch.x = bounds.x - style->touch_padding.x;
20590 touch.y = bounds.y - style->touch_padding.y;
20591 touch.w = bounds.w + style->touch_padding.x * 2;
20592 touch.h = bounds.h + style->touch_padding.y * 2;
20593 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
20594 *value = !(*value);
20595
20596 icon.y = bounds.y + style->padding.y;
20597 icon.w = icon.h = bounds.h - 2 * style->padding.y;
20598 if (align & NK_TEXT_ALIGN_LEFT) {
20599 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
20600 icon.x = NK_MAX(icon.x, 0);
20601 } else icon.x = bounds.x + 2 * style->padding.x;
20602
20603 icon.x += style->image_padding.x;
20604 icon.y += style->image_padding.y;
20605 icon.w -= 2 * style->image_padding.x;
20606 icon.h -= 2 * style->image_padding.y;
20607
20608 /* draw selectable */
20609 if (style->draw_begin) style->draw_begin(out, style->userdata);
20610 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font);
20611 if (style->draw_end) style->draw_end(out, style->userdata);
20612 return old_value != *value;
20613}
20614
20615NK_API int
20616nk_selectable_text(struct nk_context *ctx, const char *str, int len,
20617 nk_flags align, int *value)
20618{
20619 struct nk_window *win;
20620 struct nk_panel *layout;
20621 const struct nk_input *in;
20622 const struct nk_style *style;
20623
20624 enum nk_widget_layout_states state;
20625 struct nk_rect bounds;
20626
20627 NK_ASSERT(ctx);
20628 NK_ASSERT(value);
20629 NK_ASSERT(ctx->current);
20630 NK_ASSERT(ctx->current->layout);
20631 if (!ctx || !ctx->current || !ctx->current->layout || !value)
20632 return 0;
20633
20634 win = ctx->current;
20635 layout = win->layout;
20636 style = &ctx->style;
20637
20638 state = nk_widget(&bounds, ctx);
20639 if (!state) return 0;
20640 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20641 return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
20642 str, len, align, value, &style->selectable, in, style->font);
20643}
20644NK_API int
20645nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
20646 const char *str, int len, nk_flags align, int *value)
20647{
20648 struct nk_window *win;
20649 struct nk_panel *layout;
20650 const struct nk_input *in;
20651 const struct nk_style *style;
20652
20653 enum nk_widget_layout_states state;
20654 struct nk_rect bounds;
20655
20656 NK_ASSERT(ctx);
20657 NK_ASSERT(value);
20658 NK_ASSERT(ctx->current);
20659 NK_ASSERT(ctx->current->layout);
20660 if (!ctx || !ctx->current || !ctx->current->layout || !value)
20661 return 0;
20662
20663 win = ctx->current;
20664 layout = win->layout;
20665 style = &ctx->style;
20666
20667 state = nk_widget(&bounds, ctx);
20668 if (!state) return 0;
20669 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20670 return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
20671 str, len, align, value, &img, &style->selectable, in, style->font);
20672}
20673NK_API int
20675 const char *str, int len, nk_flags align, int *value)
20676{
20677 struct nk_window *win;
20678 struct nk_panel *layout;
20679 const struct nk_input *in;
20680 const struct nk_style *style;
20681
20682 enum nk_widget_layout_states state;
20683 struct nk_rect bounds;
20684
20685 NK_ASSERT(ctx);
20686 NK_ASSERT(value);
20687 NK_ASSERT(ctx->current);
20688 NK_ASSERT(ctx->current->layout);
20689 if (!ctx || !ctx->current || !ctx->current->layout || !value)
20690 return 0;
20691
20692 win = ctx->current;
20693 layout = win->layout;
20694 style = &ctx->style;
20695
20696 state = nk_widget(&bounds, ctx);
20697 if (!state) return 0;
20698 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20699 return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20700 str, len, align, value, sym, &style->selectable, in, style->font);
20701}
20702NK_API int
20704 const char *title, nk_flags align, int *value)
20705{
20706 return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
20707}
20708NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
20709 nk_flags align, int value)
20710{
20711 nk_selectable_text(ctx, str, len, align, &value);return value;
20712}
20713NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
20714{
20715 return nk_selectable_text(ctx, str, nk_strlen(str), align, value);
20716}
20717NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
20718 const char *str, nk_flags align, int *value)
20719{
20720 return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);
20721}
20722NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
20723{
20724 nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;
20725}
20726NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img,
20727 const char *str, nk_flags align, int value)
20728{
20729 nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;
20730}
20731NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img,
20732 const char *str, int len, nk_flags align, int value)
20733{
20734 nk_selectable_image_text(ctx, img, str, len, align, &value);return value;
20735}
20736NK_API int
20737nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
20738 const char *title, int title_len, nk_flags align, int value)
20739{
20740 nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value;
20741}
20742NK_API int
20744 const char *title, nk_flags align, int value)
20745{
20746 return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
20747}
20748
20749
20750
20751
20752/* ===============================================================
20753 *
20754 * SLIDER
20755 *
20756 * ===============================================================*/
20757NK_LIB float
20758nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
20759 struct nk_rect *visual_cursor, struct nk_input *in,
20760 struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
20761 float slider_step, float slider_steps)
20762{
20763 int left_mouse_down;
20764 int left_mouse_click_in_cursor;
20765
20766 /* check if visual cursor is being dragged */
20767 nk_widget_state_reset(state);
20768 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
20769 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
20770 NK_BUTTON_LEFT, *visual_cursor, nk_true);
20771
20772 if (left_mouse_down && left_mouse_click_in_cursor) {
20773 float ratio = 0;
20774 const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
20775 const float pxstep = bounds.w / slider_steps;
20776
20777 /* only update value if the next slider step is reached */
20778 *state = NK_WIDGET_STATE_ACTIVE;
20779 if (NK_ABS(d) >= pxstep) {
20780 const float steps = (float)((int)(NK_ABS(d) / pxstep));
20781 slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
20782 slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
20783 ratio = (slider_value - slider_min)/slider_step;
20784 logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
20785 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
20786 }
20787 }
20788
20789 /* slider widget state */
20790 if (nk_input_is_mouse_hovering_rect(in, bounds))
20791 *state = NK_WIDGET_STATE_HOVERED;
20792 if (*state & NK_WIDGET_STATE_HOVER &&
20794 *state |= NK_WIDGET_STATE_ENTERED;
20795 else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
20796 *state |= NK_WIDGET_STATE_LEFT;
20797 return slider_value;
20798}
20799NK_LIB void
20800nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
20801 const struct nk_style_slider *style, const struct nk_rect *bounds,
20802 const struct nk_rect *visual_cursor, float min, float value, float max)
20803{
20804 struct nk_rect fill;
20805 struct nk_rect bar;
20806 const struct nk_style_item *background;
20807
20808 /* select correct slider images/colors */
20809 struct nk_color bar_color;
20810 const struct nk_style_item *cursor;
20811
20812 NK_UNUSED(min);
20813 NK_UNUSED(max);
20814 NK_UNUSED(value);
20815
20816 if (state & NK_WIDGET_STATE_ACTIVED) {
20817 background = &style->active;
20818 bar_color = style->bar_active;
20819 cursor = &style->cursor_active;
20820 } else if (state & NK_WIDGET_STATE_HOVER) {
20821 background = &style->hover;
20822 bar_color = style->bar_hover;
20823 cursor = &style->cursor_hover;
20824 } else {
20825 background = &style->normal;
20826 bar_color = style->bar_normal;
20827 cursor = &style->cursor_normal;
20828 }
20829 /* calculate slider background bar */
20830 bar.x = bounds->x;
20831 bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
20832 bar.w = bounds->w;
20833 bar.h = bounds->h/6;
20834
20835 /* filled background bar style */
20836 fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
20837 fill.x = bar.x;
20838 fill.y = bar.y;
20839 fill.h = bar.h;
20840
20841 /* draw background */
20842 if (background->type == NK_STYLE_ITEM_IMAGE) {
20843 nk_draw_image(out, *bounds, &background->data.image, nk_white);
20844 } else {
20845 nk_fill_rect(out, *bounds, style->rounding, background->data.color);
20846 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
20847 }
20848
20849 /* draw slider bar */
20850 nk_fill_rect(out, bar, style->rounding, bar_color);
20851 nk_fill_rect(out, fill, style->rounding, style->bar_filled);
20852
20853 /* draw cursor */
20854 if (cursor->type == NK_STYLE_ITEM_IMAGE)
20855 nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
20856 else nk_fill_circle(out, *visual_cursor, cursor->data.color);
20857}
20858NK_LIB float
20859nk_do_slider(nk_flags *state,
20860 struct nk_command_buffer *out, struct nk_rect bounds,
20861 float min, float val, float max, float step,
20862 const struct nk_style_slider *style, struct nk_input *in,
20863 const struct nk_user_font *font)
20864{
20865 float slider_range;
20866 float slider_min;
20867 float slider_max;
20868 float slider_value;
20869 float slider_steps;
20870 float cursor_offset;
20871
20872 struct nk_rect visual_cursor;
20873 struct nk_rect logical_cursor;
20874
20875 NK_ASSERT(style);
20876 NK_ASSERT(out);
20877 if (!out || !style)
20878 return 0;
20879
20880 /* remove padding from slider bounds */
20881 bounds.x = bounds.x + style->padding.x;
20882 bounds.y = bounds.y + style->padding.y;
20883 bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
20884 bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
20885 bounds.w -= 2 * style->padding.x;
20886 bounds.h -= 2 * style->padding.y;
20887
20888 /* optional buttons */
20889 if (style->show_buttons) {
20890 nk_flags ws;
20891 struct nk_rect button;
20892 button.y = bounds.y;
20893 button.w = bounds.h;
20894 button.h = bounds.h;
20895
20896 /* decrement button */
20897 button.x = bounds.x;
20898 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
20899 &style->dec_button, in, font))
20900 val -= step;
20901
20902 /* increment button */
20903 button.x = (bounds.x + bounds.w) - button.w;
20904 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
20905 &style->inc_button, in, font))
20906 val += step;
20907
20908 bounds.x = bounds.x + button.w + style->spacing.x;
20909 bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
20910 }
20911
20912 /* remove one cursor size to support visual cursor */
20913 bounds.x += style->cursor_size.x*0.5f;
20914 bounds.w -= style->cursor_size.x;
20915
20916 /* make sure the provided values are correct */
20917 slider_max = NK_MAX(min, max);
20918 slider_min = NK_MIN(min, max);
20919 slider_value = NK_CLAMP(slider_min, val, slider_max);
20920 slider_range = slider_max - slider_min;
20921 slider_steps = slider_range / step;
20922 cursor_offset = (slider_value - slider_min) / step;
20923
20924 /* calculate cursor
20925 Basically you have two cursors. One for visual representation and interaction
20926 and one for updating the actual cursor value. */
20927 logical_cursor.h = bounds.h;
20928 logical_cursor.w = bounds.w / slider_steps;
20929 logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
20930 logical_cursor.y = bounds.y;
20931
20932 visual_cursor.h = style->cursor_size.y;
20933 visual_cursor.w = style->cursor_size.x;
20934 visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
20935 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
20936
20937 slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
20938 in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
20939 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
20940
20941 /* draw slider */
20942 if (style->draw_begin) style->draw_begin(out, style->userdata);
20943 nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
20944 if (style->draw_end) style->draw_end(out, style->userdata);
20945 return slider_value;
20946}
20947NK_API int
20948nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
20949 float value_step)
20950{
20951 struct nk_window *win;
20952 struct nk_panel *layout;
20953 struct nk_input *in;
20954 const struct nk_style *style;
20955
20956 int ret = 0;
20957 float old_value;
20958 struct nk_rect bounds;
20959 enum nk_widget_layout_states state;
20960
20961 NK_ASSERT(ctx);
20962 NK_ASSERT(ctx->current);
20963 NK_ASSERT(ctx->current->layout);
20964 NK_ASSERT(value);
20965 if (!ctx || !ctx->current || !ctx->current->layout || !value)
20966 return ret;
20967
20968 win = ctx->current;
20969 style = &ctx->style;
20970 layout = win->layout;
20971
20972 state = nk_widget(&bounds, ctx);
20973 if (!state) return ret;
20974 in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20975
20976 old_value = *value;
20977 *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
20978 old_value, max_value, value_step, &style->slider, in, style->font);
20979 return (old_value > *value || old_value < *value);
20980}
20981NK_API float
20982nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
20983{
20984 nk_slider_float(ctx, min, &val, max, step); return val;
20985}
20986NK_API int
20987nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
20988{
20989 float value = (float)val;
20990 nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
20991 return (int)value;
20992}
20993NK_API int
20994nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
20995{
20996 int ret;
20997 float value = (float)*val;
20998 ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
20999 *val = (int)value;
21000 return ret;
21001}
21002
21003
21004
21005
21006/* ===============================================================
21007 *
21008 * PROGRESS
21009 *
21010 * ===============================================================*/
21012nk_progress_behavior(nk_flags *state, struct nk_input *in,
21013 struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable)
21014{
21015 int left_mouse_down = 0;
21016 int left_mouse_click_in_cursor = 0;
21017
21018 nk_widget_state_reset(state);
21019 if (!in || !modifiable) return value;
21020 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
21021 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
21022 NK_BUTTON_LEFT, cursor, nk_true);
21024 *state = NK_WIDGET_STATE_HOVERED;
21025
21026 if (in && left_mouse_down && left_mouse_click_in_cursor) {
21027 if (left_mouse_down && left_mouse_click_in_cursor) {
21028 float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w;
21029 value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max);
21030 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f;
21031 *state |= NK_WIDGET_STATE_ACTIVE;
21032 }
21033 }
21034 /* set progressbar widget state */
21036 *state |= NK_WIDGET_STATE_ENTERED;
21038 *state |= NK_WIDGET_STATE_LEFT;
21039 return value;
21040}
21041NK_LIB void
21042nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
21043 const struct nk_style_progress *style, const struct nk_rect *bounds,
21044 const struct nk_rect *scursor, nk_size value, nk_size max)
21045{
21046 const struct nk_style_item *background;
21047 const struct nk_style_item *cursor;
21048
21049 NK_UNUSED(max);
21050 NK_UNUSED(value);
21051
21052 /* select correct colors/images to draw */
21053 if (state & NK_WIDGET_STATE_ACTIVED) {
21054 background = &style->active;
21055 cursor = &style->cursor_active;
21056 } else if (state & NK_WIDGET_STATE_HOVER){
21057 background = &style->hover;
21058 cursor = &style->cursor_hover;
21059 } else {
21060 background = &style->normal;
21061 cursor = &style->cursor_normal;
21062 }
21063
21064 /* draw background */
21065 if (background->type == NK_STYLE_ITEM_COLOR) {
21066 nk_fill_rect(out, *bounds, style->rounding, background->data.color);
21067 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
21068 } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
21069
21070 /* draw cursor */
21071 if (cursor->type == NK_STYLE_ITEM_COLOR) {
21072 nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
21073 nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
21074 } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
21075}
21077nk_do_progress(nk_flags *state,
21078 struct nk_command_buffer *out, struct nk_rect bounds,
21079 nk_size value, nk_size max, int modifiable,
21080 const struct nk_style_progress *style, struct nk_input *in)
21081{
21082 float prog_scale;
21083 nk_size prog_value;
21084 struct nk_rect cursor;
21085
21086 NK_ASSERT(style);
21087 NK_ASSERT(out);
21088 if (!out || !style) return 0;
21089
21090 /* calculate progressbar cursor */
21091 cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
21092 cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
21093 cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
21094 prog_scale = (float)value / (float)max;
21095
21096 /* update progressbar */
21097 prog_value = NK_MIN(value, max);
21098 prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable);
21099 cursor.w = cursor.w * prog_scale;
21100
21101 /* draw progressbar */
21102 if (style->draw_begin) style->draw_begin(out, style->userdata);
21103 nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
21104 if (style->draw_end) style->draw_end(out, style->userdata);
21105 return prog_value;
21106}
21107NK_API int
21108nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
21109{
21110 struct nk_window *win;
21111 struct nk_panel *layout;
21112 const struct nk_style *style;
21113 struct nk_input *in;
21114
21115 struct nk_rect bounds;
21116 enum nk_widget_layout_states state;
21117 nk_size old_value;
21118
21119 NK_ASSERT(ctx);
21120 NK_ASSERT(cur);
21121 NK_ASSERT(ctx->current);
21122 NK_ASSERT(ctx->current->layout);
21123 if (!ctx || !ctx->current || !ctx->current->layout || !cur)
21124 return 0;
21125
21126 win = ctx->current;
21127 style = &ctx->style;
21128 layout = win->layout;
21129 state = nk_widget(&bounds, ctx);
21130 if (!state) return 0;
21131
21132 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21133 old_value = *cur;
21134 *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
21135 *cur, max, is_modifyable, &style->progress, in);
21136 return (*cur != old_value);
21137}
21139nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
21140{
21141 nk_progress(ctx, &cur, max, modifyable);
21142 return cur;
21143}
21144
21145
21146
21147
21148/* ===============================================================
21149 *
21150 * SCROLLBAR
21151 *
21152 * ===============================================================*/
21153NK_LIB float
21154nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
21155 int has_scrolling, const struct nk_rect *scroll,
21156 const struct nk_rect *cursor, const struct nk_rect *empty0,
21157 const struct nk_rect *empty1, float scroll_offset,
21158 float target, float scroll_step, enum nk_orientation o)
21159{
21160 nk_flags ws = 0;
21161 int left_mouse_down;
21162 int left_mouse_clicked;
21163 int left_mouse_click_in_cursor;
21164 float scroll_delta;
21165
21166 nk_widget_state_reset(state);
21167 if (!in) return scroll_offset;
21168
21169 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
21170 left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked;
21171 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
21172 NK_BUTTON_LEFT, *cursor, nk_true);
21173 if (nk_input_is_mouse_hovering_rect(in, *scroll))
21174 *state = NK_WIDGET_STATE_HOVERED;
21175
21176 scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
21177 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
21178 /* update cursor by mouse dragging */
21179 float pixel, delta;
21180 *state = NK_WIDGET_STATE_ACTIVE;
21181 if (o == NK_VERTICAL) {
21182 float cursor_y;
21183 pixel = in->mouse.delta.y;
21184 delta = (pixel / scroll->h) * target;
21185 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
21186 cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
21187 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
21188 } else {
21189 float cursor_x;
21190 pixel = in->mouse.delta.x;
21191 delta = (pixel / scroll->w) * target;
21192 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
21193 cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
21194 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
21195 }
21196 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
21197 nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
21198 /* scroll page up by click on empty space or shortcut */
21199 if (o == NK_VERTICAL)
21200 scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
21201 else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
21202 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
21203 nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
21204 /* scroll page down by click on empty space or shortcut */
21205 if (o == NK_VERTICAL)
21206 scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
21207 else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
21208 } else if (has_scrolling) {
21209 if ((scroll_delta < 0 || (scroll_delta > 0))) {
21210 /* update cursor by mouse scrolling */
21211 scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
21212 if (o == NK_VERTICAL)
21213 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
21214 else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
21216 /* update cursor to the beginning */
21217 if (o == NK_VERTICAL) scroll_offset = 0;
21219 /* update cursor to the end */
21220 if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
21221 }
21222 }
21223 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
21224 *state |= NK_WIDGET_STATE_ENTERED;
21225 else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
21226 *state |= NK_WIDGET_STATE_LEFT;
21227 return scroll_offset;
21228}
21229NK_LIB void
21230nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
21231 const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
21232 const struct nk_rect *scroll)
21233{
21234 const struct nk_style_item *background;
21235 const struct nk_style_item *cursor;
21236
21237 /* select correct colors/images to draw */
21238 if (state & NK_WIDGET_STATE_ACTIVED) {
21239 background = &style->active;
21240 cursor = &style->cursor_active;
21241 } else if (state & NK_WIDGET_STATE_HOVER) {
21242 background = &style->hover;
21243 cursor = &style->cursor_hover;
21244 } else {
21245 background = &style->normal;
21246 cursor = &style->cursor_normal;
21247 }
21248
21249 /* draw background */
21250 if (background->type == NK_STYLE_ITEM_COLOR) {
21251 nk_fill_rect(out, *bounds, style->rounding, background->data.color);
21252 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
21253 } else {
21254 nk_draw_image(out, *bounds, &background->data.image, nk_white);
21255 }
21256
21257 /* draw cursor */
21258 if (cursor->type == NK_STYLE_ITEM_COLOR) {
21259 nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
21260 nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
21261 } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
21262}
21263NK_LIB float
21264nk_do_scrollbarv(nk_flags *state,
21265 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
21266 float offset, float target, float step, float button_pixel_inc,
21267 const struct nk_style_scrollbar *style, struct nk_input *in,
21268 const struct nk_user_font *font)
21269{
21270 struct nk_rect empty_north;
21271 struct nk_rect empty_south;
21272 struct nk_rect cursor;
21273
21274 float scroll_step;
21275 float scroll_offset;
21276 float scroll_off;
21277 float scroll_ratio;
21278
21279 NK_ASSERT(out);
21280 NK_ASSERT(style);
21281 NK_ASSERT(state);
21282 if (!out || !style) return 0;
21283
21284 scroll.w = NK_MAX(scroll.w, 1);
21285 scroll.h = NK_MAX(scroll.h, 0);
21286 if (target <= scroll.h) return 0;
21287
21288 /* optional scrollbar buttons */
21289 if (style->show_buttons) {
21290 nk_flags ws;
21291 float scroll_h;
21292 struct nk_rect button;
21293
21294 button.x = scroll.x;
21295 button.w = scroll.w;
21296 button.h = scroll.w;
21297
21298 scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
21299 scroll_step = NK_MIN(step, button_pixel_inc);
21300
21301 /* decrement button */
21302 button.y = scroll.y;
21303 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
21304 NK_BUTTON_REPEATER, &style->dec_button, in, font))
21305 offset = offset - scroll_step;
21306
21307 /* increment button */
21308 button.y = scroll.y + scroll.h - button.h;
21309 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
21310 NK_BUTTON_REPEATER, &style->inc_button, in, font))
21311 offset = offset + scroll_step;
21312
21313 scroll.y = scroll.y + button.h;
21314 scroll.h = scroll_h;
21315 }
21316
21317 /* calculate scrollbar constants */
21318 scroll_step = NK_MIN(step, scroll.h);
21319 scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
21320 scroll_ratio = scroll.h / target;
21321 scroll_off = scroll_offset / target;
21322
21323 /* calculate scrollbar cursor bounds */
21324 cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
21325 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
21326 cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
21327 cursor.x = scroll.x + style->border + style->padding.x;
21328
21329 /* calculate empty space around cursor */
21330 empty_north.x = scroll.x;
21331 empty_north.y = scroll.y;
21332 empty_north.w = scroll.w;
21333 empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
21334
21335 empty_south.x = scroll.x;
21336 empty_south.y = cursor.y + cursor.h;
21337 empty_south.w = scroll.w;
21338 empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
21339
21340 /* update scrollbar */
21341 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
21342 &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
21343 scroll_off = scroll_offset / target;
21344 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
21345
21346 /* draw scrollbar */
21347 if (style->draw_begin) style->draw_begin(out, style->userdata);
21348 nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
21349 if (style->draw_end) style->draw_end(out, style->userdata);
21350 return scroll_offset;
21351}
21352NK_LIB float
21353nk_do_scrollbarh(nk_flags *state,
21354 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
21355 float offset, float target, float step, float button_pixel_inc,
21356 const struct nk_style_scrollbar *style, struct nk_input *in,
21357 const struct nk_user_font *font)
21358{
21359 struct nk_rect cursor;
21360 struct nk_rect empty_west;
21361 struct nk_rect empty_east;
21362
21363 float scroll_step;
21364 float scroll_offset;
21365 float scroll_off;
21366 float scroll_ratio;
21367
21368 NK_ASSERT(out);
21369 NK_ASSERT(style);
21370 if (!out || !style) return 0;
21371
21372 /* scrollbar background */
21373 scroll.h = NK_MAX(scroll.h, 1);
21374 scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
21375 if (target <= scroll.w) return 0;
21376
21377 /* optional scrollbar buttons */
21378 if (style->show_buttons) {
21379 nk_flags ws;
21380 float scroll_w;
21381 struct nk_rect button;
21382 button.y = scroll.y;
21383 button.w = scroll.h;
21384 button.h = scroll.h;
21385
21386 scroll_w = scroll.w - 2 * button.w;
21387 scroll_step = NK_MIN(step, button_pixel_inc);
21388
21389 /* decrement button */
21390 button.x = scroll.x;
21391 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
21392 NK_BUTTON_REPEATER, &style->dec_button, in, font))
21393 offset = offset - scroll_step;
21394
21395 /* increment button */
21396 button.x = scroll.x + scroll.w - button.w;
21397 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
21398 NK_BUTTON_REPEATER, &style->inc_button, in, font))
21399 offset = offset + scroll_step;
21400
21401 scroll.x = scroll.x + button.w;
21402 scroll.w = scroll_w;
21403 }
21404
21405 /* calculate scrollbar constants */
21406 scroll_step = NK_MIN(step, scroll.w);
21407 scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
21408 scroll_ratio = scroll.w / target;
21409 scroll_off = scroll_offset / target;
21410
21411 /* calculate cursor bounds */
21412 cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
21413 cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
21414 cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
21415 cursor.y = scroll.y + style->border + style->padding.y;
21416
21417 /* calculate empty space around cursor */
21418 empty_west.x = scroll.x;
21419 empty_west.y = scroll.y;
21420 empty_west.w = cursor.x - scroll.x;
21421 empty_west.h = scroll.h;
21422
21423 empty_east.x = cursor.x + cursor.w;
21424 empty_east.y = scroll.y;
21425 empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
21426 empty_east.h = scroll.h;
21427
21428 /* update scrollbar */
21429 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
21430 &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
21431 scroll_off = scroll_offset / target;
21432 cursor.x = scroll.x + (scroll_off * scroll.w);
21433
21434 /* draw scrollbar */
21435 if (style->draw_begin) style->draw_begin(out, style->userdata);
21436 nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
21437 if (style->draw_end) style->draw_end(out, style->userdata);
21438 return scroll_offset;
21439}
21440
21441
21442
21443
21444/* ===============================================================
21445 *
21446 * TEXT EDITOR
21447 *
21448 * ===============================================================*/
21449/* stb_textedit.h - v1.8 - public domain - Sean Barrett */
21450struct nk_text_find {
21451 float x,y; /* position of n'th character */
21452 float height; /* height of line */
21453 int first_char, length; /* first char of row, and length */
21454 int prev_first; /*_ first char of previous row */
21455};
21456
21457struct nk_text_edit_row {
21458 float x0,x1;
21459 /* starting x location, end x location (allows for align=right, etc) */
21460 float baseline_y_delta;
21461 /* position of baseline relative to previous row's baseline*/
21462 float ymin,ymax;
21463 /* height of row above and below baseline */
21464 int num_chars;
21465};
21466
21467/* forward declarations */
21468NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
21469NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
21470NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
21471#define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
21472
21473NK_INTERN float
21474nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
21475 const struct nk_user_font *font)
21476{
21477 int len = 0;
21478 nk_rune unicode = 0;
21479 const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
21480 return font->width(font->userdata, font->height, str, len);
21481}
21482NK_INTERN void
21483nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
21484 int line_start_id, float row_height, const struct nk_user_font *font)
21485{
21486 int l;
21487 int glyphs = 0;
21488 nk_rune unicode;
21489 const char *remaining;
21490 int len = nk_str_len_char(&edit->string);
21491 const char *end = nk_str_get_const(&edit->string) + len;
21492 const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
21493 const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
21494 text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
21495
21496 r->x0 = 0.0f;
21497 r->x1 = size.x;
21498 r->baseline_y_delta = size.y;
21499 r->ymin = 0.0f;
21500 r->ymax = size.y;
21501 r->num_chars = glyphs;
21502}
21503NK_INTERN int
21504nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
21505 const struct nk_user_font *font, float row_height)
21506{
21507 struct nk_text_edit_row r;
21508 int n = edit->string.len;
21509 float base_y = 0, prev_x;
21510 int i=0, k;
21511
21512 r.x0 = r.x1 = 0;
21513 r.ymin = r.ymax = 0;
21514 r.num_chars = 0;
21515
21516 /* search rows to find one that straddles 'y' */
21517 while (i < n) {
21518 nk_textedit_layout_row(&r, edit, i, row_height, font);
21519 if (r.num_chars <= 0)
21520 return n;
21521
21522 if (i==0 && y < base_y + r.ymin)
21523 return 0;
21524
21525 if (y < base_y + r.ymax)
21526 break;
21527
21528 i += r.num_chars;
21529 base_y += r.baseline_y_delta;
21530 }
21531
21532 /* below all text, return 'after' last character */
21533 if (i >= n)
21534 return n;
21535
21536 /* check if it's before the beginning of the line */
21537 if (x < r.x0)
21538 return i;
21539
21540 /* check if it's before the end of the line */
21541 if (x < r.x1) {
21542 /* search characters in row for one that straddles 'x' */
21543 k = i;
21544 prev_x = r.x0;
21545 for (i=0; i < r.num_chars; ++i) {
21546 float w = nk_textedit_get_width(edit, k, i, font);
21547 if (x < prev_x+w) {
21548 if (x < prev_x+w/2)
21549 return k+i;
21550 else return k+i+1;
21551 }
21552 prev_x += w;
21553 }
21554 /* shouldn't happen, but if it does, fall through to end-of-line case */
21555 }
21556
21557 /* if the last character is a newline, return that.
21558 * otherwise return 'after' the last character */
21559 if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
21560 return i+r.num_chars-1;
21561 else return i+r.num_chars;
21562}
21563NK_LIB void
21564nk_textedit_click(struct nk_text_edit *state, float x, float y,
21565 const struct nk_user_font *font, float row_height)
21566{
21567 /* API click: on mouse down, move the cursor to the clicked location,
21568 * and reset the selection */
21569 state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
21570 state->select_start = state->cursor;
21571 state->select_end = state->cursor;
21572 state->has_preferred_x = 0;
21573}
21574NK_LIB void
21575nk_textedit_drag(struct nk_text_edit *state, float x, float y,
21576 const struct nk_user_font *font, float row_height)
21577{
21578 /* API drag: on mouse drag, move the cursor and selection endpoint
21579 * to the clicked location */
21580 int p = nk_textedit_locate_coord(state, x, y, font, row_height);
21581 if (state->select_start == state->select_end)
21582 state->select_start = state->cursor;
21583 state->cursor = state->select_end = p;
21584}
21585NK_INTERN void
21586nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
21587 int n, int single_line, const struct nk_user_font *font, float row_height)
21588{
21589 /* find the x/y location of a character, and remember info about the previous
21590 * row in case we get a move-up event (for page up, we'll have to rescan) */
21591 struct nk_text_edit_row r;
21592 int prev_start = 0;
21593 int z = state->string.len;
21594 int i=0, first;
21595
21596 nk_zero_struct(r);
21597 if (n == z) {
21598 /* if it's at the end, then find the last line -- simpler than trying to
21599 explicitly handle this case in the regular code */
21600 nk_textedit_layout_row(&r, state, 0, row_height, font);
21601 if (single_line) {
21602 find->first_char = 0;
21603 find->length = z;
21604 } else {
21605 while (i < z) {
21606 prev_start = i;
21607 i += r.num_chars;
21608 nk_textedit_layout_row(&r, state, i, row_height, font);
21609 }
21610
21611 find->first_char = i;
21612 find->length = r.num_chars;
21613 }
21614 find->x = r.x1;
21615 find->y = r.ymin;
21616 find->height = r.ymax - r.ymin;
21617 find->prev_first = prev_start;
21618 return;
21619 }
21620
21621 /* search rows to find the one that straddles character n */
21622 find->y = 0;
21623
21624 for(;;) {
21625 nk_textedit_layout_row(&r, state, i, row_height, font);
21626 if (n < i + r.num_chars) break;
21627 prev_start = i;
21628 i += r.num_chars;
21629 find->y += r.baseline_y_delta;
21630 }
21631
21632 find->first_char = first = i;
21633 find->length = r.num_chars;
21634 find->height = r.ymax - r.ymin;
21635 find->prev_first = prev_start;
21636
21637 /* now scan to find xpos */
21638 find->x = r.x0;
21639 for (i=0; first+i < n; ++i)
21640 find->x += nk_textedit_get_width(state, first, i, font);
21641}
21642NK_INTERN void
21643nk_textedit_clamp(struct nk_text_edit *state)
21644{
21645 /* make the selection/cursor state valid if client altered the string */
21646 int n = state->string.len;
21647 if (NK_TEXT_HAS_SELECTION(state)) {
21648 if (state->select_start > n) state->select_start = n;
21649 if (state->select_end > n) state->select_end = n;
21650 /* if clamping forced them to be equal, move the cursor to match */
21651 if (state->select_start == state->select_end)
21652 state->cursor = state->select_start;
21653 }
21654 if (state->cursor > n) state->cursor = n;
21655}
21656NK_API void
21657nk_textedit_delete(struct nk_text_edit *state, int where, int len)
21658{
21659 /* delete characters while updating undo */
21660 nk_textedit_makeundo_delete(state, where, len);
21661 nk_str_delete_runes(&state->string, where, len);
21662 state->has_preferred_x = 0;
21663}
21664NK_API void
21666{
21667 /* delete the section */
21668 nk_textedit_clamp(state);
21669 if (NK_TEXT_HAS_SELECTION(state)) {
21670 if (state->select_start < state->select_end) {
21671 nk_textedit_delete(state, state->select_start,
21672 state->select_end - state->select_start);
21673 state->select_end = state->cursor = state->select_start;
21674 } else {
21675 nk_textedit_delete(state, state->select_end,
21676 state->select_start - state->select_end);
21677 state->select_start = state->cursor = state->select_end;
21678 }
21679 state->has_preferred_x = 0;
21680 }
21681}
21682NK_INTERN void
21683nk_textedit_sortselection(struct nk_text_edit *state)
21684{
21685 /* canonicalize the selection so start <= end */
21686 if (state->select_end < state->select_start) {
21687 int temp = state->select_end;
21688 state->select_end = state->select_start;
21689 state->select_start = temp;
21690 }
21691}
21692NK_INTERN void
21693nk_textedit_move_to_first(struct nk_text_edit *state)
21694{
21695 /* move cursor to first character of selection */
21696 if (NK_TEXT_HAS_SELECTION(state)) {
21697 nk_textedit_sortselection(state);
21698 state->cursor = state->select_start;
21699 state->select_end = state->select_start;
21700 state->has_preferred_x = 0;
21701 }
21702}
21703NK_INTERN void
21704nk_textedit_move_to_last(struct nk_text_edit *state)
21705{
21706 /* move cursor to last character of selection */
21707 if (NK_TEXT_HAS_SELECTION(state)) {
21708 nk_textedit_sortselection(state);
21709 nk_textedit_clamp(state);
21710 state->cursor = state->select_end;
21711 state->select_start = state->select_end;
21712 state->has_preferred_x = 0;
21713 }
21714}
21715NK_INTERN int
21716nk_is_word_boundary( struct nk_text_edit *state, int idx)
21717{
21718 int len;
21719 nk_rune c;
21720 if (idx <= 0) return 1;
21721 if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
21722 return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
21723 c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
21724 c == '|');
21725}
21726NK_INTERN int
21727nk_textedit_move_to_word_previous(struct nk_text_edit *state)
21728{
21729 int c = state->cursor - 1;
21730 while( c >= 0 && !nk_is_word_boundary(state, c))
21731 --c;
21732
21733 if( c < 0 )
21734 c = 0;
21735
21736 return c;
21737}
21738NK_INTERN int
21739nk_textedit_move_to_word_next(struct nk_text_edit *state)
21740{
21741 const int len = state->string.len;
21742 int c = state->cursor+1;
21743 while( c < len && !nk_is_word_boundary(state, c))
21744 ++c;
21745
21746 if( c > len )
21747 c = len;
21748
21749 return c;
21750}
21751NK_INTERN void
21752nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
21753{
21754 /* update selection and cursor to match each other */
21755 if (!NK_TEXT_HAS_SELECTION(state))
21756 state->select_start = state->select_end = state->cursor;
21757 else state->cursor = state->select_end;
21758}
21759NK_API int
21760nk_textedit_cut(struct nk_text_edit *state)
21761{
21762 /* API cut: delete selection */
21763 if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
21764 return 0;
21765 if (NK_TEXT_HAS_SELECTION(state)) {
21766 nk_textedit_delete_selection(state); /* implicitly clamps */
21767 state->has_preferred_x = 0;
21768 return 1;
21769 }
21770 return 0;
21771}
21772NK_API int
21773nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
21774{
21775 /* API paste: replace existing selection with passed-in text */
21776 int glyphs;
21777 const char *text = (const char *) ctext;
21778 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
21779
21780 /* if there's a selection, the paste should delete it */
21781 nk_textedit_clamp(state);
21783
21784 /* try to insert the characters */
21785 glyphs = nk_utf_len(ctext, len);
21786 if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
21787 nk_textedit_makeundo_insert(state, state->cursor, glyphs);
21788 state->cursor += len;
21789 state->has_preferred_x = 0;
21790 return 1;
21791 }
21792 /* remove the undo since we didn't actually insert the characters */
21793 if (state->undo.undo_point)
21794 --state->undo.undo_point;
21795 return 0;
21796}
21797NK_API void
21798nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
21799{
21800 nk_rune unicode;
21801 int glyph_len;
21802 int text_len = 0;
21803
21804 NK_ASSERT(state);
21805 NK_ASSERT(text);
21806 if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
21807
21808 glyph_len = nk_utf_decode(text, &unicode, total_len);
21809 while ((text_len < total_len) && glyph_len)
21810 {
21811 /* don't insert a backward delete, just process the event */
21812 if (unicode == 127) goto next;
21813 /* can't add newline in single-line mode */
21814 if (unicode == '\n' && state->single_line) goto next;
21815 /* filter incoming text */
21816 if (state->filter && !state->filter(state, unicode)) goto next;
21817
21818 if (!NK_TEXT_HAS_SELECTION(state) &&
21819 state->cursor < state->string.len)
21820 {
21821 if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
21822 nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
21823 nk_str_delete_runes(&state->string, state->cursor, 1);
21824 }
21825 if (nk_str_insert_text_utf8(&state->string, state->cursor,
21826 text+text_len, 1))
21827 {
21828 ++state->cursor;
21829 state->has_preferred_x = 0;
21830 }
21831 } else {
21832 nk_textedit_delete_selection(state); /* implicitly clamps */
21833 if (nk_str_insert_text_utf8(&state->string, state->cursor,
21834 text+text_len, 1))
21835 {
21836 nk_textedit_makeundo_insert(state, state->cursor, 1);
21837 ++state->cursor;
21838 state->has_preferred_x = 0;
21839 }
21840 }
21841 next:
21842 text_len += glyph_len;
21843 glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
21844 }
21845}
21846NK_LIB void
21847nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
21848 const struct nk_user_font *font, float row_height)
21849{
21850retry:
21851 switch (key)
21852 {
21853 case NK_KEY_NONE:
21854 case NK_KEY_CTRL:
21855 case NK_KEY_ENTER:
21856 case NK_KEY_SHIFT:
21857 case NK_KEY_TAB:
21858 case NK_KEY_COPY:
21859 case NK_KEY_CUT:
21860 case NK_KEY_PASTE:
21861 case NK_KEY_MAX:
21862 default: break;
21863 case NK_KEY_TEXT_UNDO:
21864 nk_textedit_undo(state);
21865 state->has_preferred_x = 0;
21866 break;
21867
21868 case NK_KEY_TEXT_REDO:
21869 nk_textedit_redo(state);
21870 state->has_preferred_x = 0;
21871 break;
21872
21875 state->has_preferred_x = 0;
21876 break;
21877
21879 if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
21881 break;
21883 if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
21885 break;
21887 if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
21890 break;
21891
21892 case NK_KEY_LEFT:
21893 if (shift_mod) {
21894 nk_textedit_clamp(state);
21895 nk_textedit_prep_selection_at_cursor(state);
21896 /* move selection left */
21897 if (state->select_end > 0)
21898 --state->select_end;
21899 state->cursor = state->select_end;
21900 state->has_preferred_x = 0;
21901 } else {
21902 /* if currently there's a selection,
21903 * move cursor to start of selection */
21904 if (NK_TEXT_HAS_SELECTION(state))
21905 nk_textedit_move_to_first(state);
21906 else if (state->cursor > 0)
21907 --state->cursor;
21908 state->has_preferred_x = 0;
21909 } break;
21910
21911 case NK_KEY_RIGHT:
21912 if (shift_mod) {
21913 nk_textedit_prep_selection_at_cursor(state);
21914 /* move selection right */
21915 ++state->select_end;
21916 nk_textedit_clamp(state);
21917 state->cursor = state->select_end;
21918 state->has_preferred_x = 0;
21919 } else {
21920 /* if currently there's a selection,
21921 * move cursor to end of selection */
21922 if (NK_TEXT_HAS_SELECTION(state))
21923 nk_textedit_move_to_last(state);
21924 else ++state->cursor;
21925 nk_textedit_clamp(state);
21926 state->has_preferred_x = 0;
21927 } break;
21928
21930 if (shift_mod) {
21931 if( !NK_TEXT_HAS_SELECTION( state ) )
21932 nk_textedit_prep_selection_at_cursor(state);
21933 state->cursor = nk_textedit_move_to_word_previous(state);
21934 state->select_end = state->cursor;
21935 nk_textedit_clamp(state );
21936 } else {
21937 if (NK_TEXT_HAS_SELECTION(state))
21938 nk_textedit_move_to_first(state);
21939 else {
21940 state->cursor = nk_textedit_move_to_word_previous(state);
21941 nk_textedit_clamp(state );
21942 }
21943 } break;
21944
21946 if (shift_mod) {
21947 if( !NK_TEXT_HAS_SELECTION( state ) )
21948 nk_textedit_prep_selection_at_cursor(state);
21949 state->cursor = nk_textedit_move_to_word_next(state);
21950 state->select_end = state->cursor;
21951 nk_textedit_clamp(state);
21952 } else {
21953 if (NK_TEXT_HAS_SELECTION(state))
21954 nk_textedit_move_to_last(state);
21955 else {
21956 state->cursor = nk_textedit_move_to_word_next(state);
21957 nk_textedit_clamp(state );
21958 }
21959 } break;
21960
21961 case NK_KEY_DOWN: {
21962 struct nk_text_find find;
21963 struct nk_text_edit_row row;
21964 int i, sel = shift_mod;
21965
21966 if (state->single_line) {
21967 /* on windows, up&down in single-line behave like left&right */
21968 key = NK_KEY_RIGHT;
21969 goto retry;
21970 }
21971
21972 if (sel)
21973 nk_textedit_prep_selection_at_cursor(state);
21974 else if (NK_TEXT_HAS_SELECTION(state))
21975 nk_textedit_move_to_last(state);
21976
21977 /* compute current position of cursor point */
21978 nk_textedit_clamp(state);
21979 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
21980 font, row_height);
21981
21982 /* now find character position down a row */
21983 if (find.length)
21984 {
21985 float x;
21986 float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
21987 int start = find.first_char + find.length;
21988
21989 state->cursor = start;
21990 nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
21991 x = row.x0;
21992
21993 for (i=0; i < row.num_chars && x < row.x1; ++i) {
21994 float dx = nk_textedit_get_width(state, start, i, font);
21995 x += dx;
21996 if (x > goal_x)
21997 break;
21998 ++state->cursor;
21999 }
22000 nk_textedit_clamp(state);
22001
22002 state->has_preferred_x = 1;
22003 state->preferred_x = goal_x;
22004 if (sel)
22005 state->select_end = state->cursor;
22006 }
22007 } break;
22008
22009 case NK_KEY_UP: {
22010 struct nk_text_find find;
22011 struct nk_text_edit_row row;
22012 int i, sel = shift_mod;
22013
22014 if (state->single_line) {
22015 /* on windows, up&down become left&right */
22016 key = NK_KEY_LEFT;
22017 goto retry;
22018 }
22019
22020 if (sel)
22021 nk_textedit_prep_selection_at_cursor(state);
22022 else if (NK_TEXT_HAS_SELECTION(state))
22023 nk_textedit_move_to_first(state);
22024
22025 /* compute current position of cursor point */
22026 nk_textedit_clamp(state);
22027 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22028 font, row_height);
22029
22030 /* can only go up if there's a previous row */
22031 if (find.prev_first != find.first_char) {
22032 /* now find character position up a row */
22033 float x;
22034 float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
22035
22036 state->cursor = find.prev_first;
22037 nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
22038 x = row.x0;
22039
22040 for (i=0; i < row.num_chars && x < row.x1; ++i) {
22041 float dx = nk_textedit_get_width(state, find.prev_first, i, font);
22042 x += dx;
22043 if (x > goal_x)
22044 break;
22045 ++state->cursor;
22046 }
22047 nk_textedit_clamp(state);
22048
22049 state->has_preferred_x = 1;
22050 state->preferred_x = goal_x;
22051 if (sel) state->select_end = state->cursor;
22052 }
22053 } break;
22054
22055 case NK_KEY_DEL:
22056 if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
22057 break;
22058 if (NK_TEXT_HAS_SELECTION(state))
22060 else {
22061 int n = state->string.len;
22062 if (state->cursor < n)
22063 nk_textedit_delete(state, state->cursor, 1);
22064 }
22065 state->has_preferred_x = 0;
22066 break;
22067
22068 case NK_KEY_BACKSPACE:
22069 if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
22070 break;
22071 if (NK_TEXT_HAS_SELECTION(state))
22073 else {
22074 nk_textedit_clamp(state);
22075 if (state->cursor > 0) {
22076 nk_textedit_delete(state, state->cursor-1, 1);
22077 --state->cursor;
22078 }
22079 }
22080 state->has_preferred_x = 0;
22081 break;
22082
22083 case NK_KEY_TEXT_START:
22084 if (shift_mod) {
22085 nk_textedit_prep_selection_at_cursor(state);
22086 state->cursor = state->select_end = 0;
22087 state->has_preferred_x = 0;
22088 } else {
22089 state->cursor = state->select_start = state->select_end = 0;
22090 state->has_preferred_x = 0;
22091 }
22092 break;
22093
22094 case NK_KEY_TEXT_END:
22095 if (shift_mod) {
22096 nk_textedit_prep_selection_at_cursor(state);
22097 state->cursor = state->select_end = state->string.len;
22098 state->has_preferred_x = 0;
22099 } else {
22100 state->cursor = state->string.len;
22101 state->select_start = state->select_end = 0;
22102 state->has_preferred_x = 0;
22103 }
22104 break;
22105
22107 if (shift_mod) {
22108 struct nk_text_find find;
22109 nk_textedit_clamp(state);
22110 nk_textedit_prep_selection_at_cursor(state);
22111 if (state->string.len && state->cursor == state->string.len)
22112 --state->cursor;
22113 nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
22114 font, row_height);
22115 state->cursor = state->select_end = find.first_char;
22116 state->has_preferred_x = 0;
22117 } else {
22118 struct nk_text_find find;
22119 if (state->string.len && state->cursor == state->string.len)
22120 --state->cursor;
22121 nk_textedit_clamp(state);
22122 nk_textedit_move_to_first(state);
22123 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22124 font, row_height);
22125 state->cursor = find.first_char;
22126 state->has_preferred_x = 0;
22127 }
22128 } break;
22129
22130 case NK_KEY_TEXT_LINE_END: {
22131 if (shift_mod) {
22132 struct nk_text_find find;
22133 nk_textedit_clamp(state);
22134 nk_textedit_prep_selection_at_cursor(state);
22135 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22136 font, row_height);
22137 state->has_preferred_x = 0;
22138 state->cursor = find.first_char + find.length;
22139 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
22140 --state->cursor;
22141 state->select_end = state->cursor;
22142 } else {
22143 struct nk_text_find find;
22144 nk_textedit_clamp(state);
22145 nk_textedit_move_to_first(state);
22146 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22147 font, row_height);
22148
22149 state->has_preferred_x = 0;
22150 state->cursor = find.first_char + find.length;
22151 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
22152 --state->cursor;
22153 }} break;
22154 }
22155}
22156NK_INTERN void
22157nk_textedit_flush_redo(struct nk_text_undo_state *state)
22158{
22161}
22162NK_INTERN void
22163nk_textedit_discard_undo(struct nk_text_undo_state *state)
22164{
22165 /* discard the oldest entry in the undo list */
22166 if (state->undo_point > 0) {
22167 /* if the 0th undo state has characters, clean those up */
22168 if (state->undo_rec[0].char_storage >= 0) {
22169 int n = state->undo_rec[0].insert_length, i;
22170 /* delete n characters from all other records */
22171 state->undo_char_point = (short)(state->undo_char_point - n);
22172 NK_MEMCPY(state->undo_char, state->undo_char + n,
22173 (nk_size)state->undo_char_point*sizeof(nk_rune));
22174 for (i=0; i < state->undo_point; ++i) {
22175 if (state->undo_rec[i].char_storage >= 0)
22176 state->undo_rec[i].char_storage = (short)
22177 (state->undo_rec[i].char_storage - n);
22178 }
22179 }
22180 --state->undo_point;
22181 NK_MEMCPY(state->undo_rec, state->undo_rec+1,
22182 (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
22183 }
22184}
22185NK_INTERN void
22186nk_textedit_discard_redo(struct nk_text_undo_state *state)
22187{
22188/* discard the oldest entry in the redo list--it's bad if this
22189 ever happens, but because undo & redo have to store the actual
22190 characters in different cases, the redo character buffer can
22191 fill up even though the undo buffer didn't */
22192 nk_size num;
22194 if (state->redo_point <= k) {
22195 /* if the k'th undo state has characters, clean those up */
22196 if (state->undo_rec[k].char_storage >= 0) {
22197 int n = state->undo_rec[k].insert_length, i;
22198 /* delete n characters from all other records */
22199 state->redo_char_point = (short)(state->redo_char_point + n);
22201 NK_MEMCPY(state->undo_char + state->redo_char_point,
22202 state->undo_char + state->redo_char_point-n, num * sizeof(char));
22203 for (i = state->redo_point; i < k; ++i) {
22204 if (state->undo_rec[i].char_storage >= 0) {
22205 state->undo_rec[i].char_storage = (short)
22206 (state->undo_rec[i].char_storage + n);
22207 }
22208 }
22209 }
22210 ++state->redo_point;
22212 if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
22213 state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
22214 }
22215}
22217nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
22218{
22219 /* any time we create a new undo record, we discard redo*/
22220 nk_textedit_flush_redo(state);
22221
22222 /* if we have no free records, we have to make room,
22223 * by sliding the existing records down */
22225 nk_textedit_discard_undo(state);
22226
22227 /* if the characters to store won't possibly fit in the buffer,
22228 * we can't undo */
22229 if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
22230 state->undo_point = 0;
22231 state->undo_char_point = 0;
22232 return 0;
22233 }
22234
22235 /* if we don't have enough free characters in the buffer,
22236 * we have to make room */
22237 while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
22238 nk_textedit_discard_undo(state);
22239 return &state->undo_rec[state->undo_point++];
22240}
22242nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
22243 int insert_len, int delete_len)
22244{
22245 struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
22246 if (r == 0)
22247 return 0;
22248
22249 r->where = pos;
22250 r->insert_length = (short) insert_len;
22251 r->delete_length = (short) delete_len;
22252
22253 if (insert_len == 0) {
22254 r->char_storage = -1;
22255 return 0;
22256 } else {
22257 r->char_storage = state->undo_char_point;
22258 state->undo_char_point = (short)(state->undo_char_point + insert_len);
22259 return &state->undo_char[r->char_storage];
22260 }
22261}
22262NK_API void
22263nk_textedit_undo(struct nk_text_edit *state)
22264{
22265 struct nk_text_undo_state *s = &state->undo;
22266 struct nk_text_undo_record u, *r;
22267 if (s->undo_point == 0)
22268 return;
22269
22270 /* we need to do two things: apply the undo record, and create a redo record */
22271 u = s->undo_rec[s->undo_point-1];
22272 r = &s->undo_rec[s->redo_point-1];
22273 r->char_storage = -1;
22274
22275 r->insert_length = u.delete_length;
22276 r->delete_length = u.insert_length;
22277 r->where = u.where;
22278
22279 if (u.delete_length)
22280 {
22281 /* if the undo record says to delete characters, then the redo record will
22282 need to re-insert the characters that get deleted, so we need to store
22283 them.
22284 there are three cases:
22285 - there's enough room to store the characters
22286 - characters stored for *redoing* don't leave room for redo
22287 - characters stored for *undoing* don't leave room for redo
22288 if the last is true, we have to bail */
22289 if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
22290 /* the undo records take up too much character space; there's no space
22291 * to store the redo characters */
22292 r->insert_length = 0;
22293 } else {
22294 int i;
22295 /* there's definitely room to store the characters eventually */
22296 while (s->undo_char_point + u.delete_length > s->redo_char_point) {
22297 /* there's currently not enough room, so discard a redo record */
22298 nk_textedit_discard_redo(s);
22299 /* should never happen: */
22301 return;
22302 }
22303
22304 r = &s->undo_rec[s->redo_point-1];
22305 r->char_storage = (short)(s->redo_char_point - u.delete_length);
22306 s->redo_char_point = (short)(s->redo_char_point - u.delete_length);
22307
22308 /* now save the characters */
22309 for (i=0; i < u.delete_length; ++i)
22310 s->undo_char[r->char_storage + i] =
22311 nk_str_rune_at(&state->string, u.where + i);
22312 }
22313 /* now we can carry out the deletion */
22314 nk_str_delete_runes(&state->string, u.where, u.delete_length);
22315 }
22316
22317 /* check type of recorded action: */
22318 if (u.insert_length) {
22319 /* easy case: was a deletion, so we need to insert n characters */
22320 nk_str_insert_text_runes(&state->string, u.where,
22321 &s->undo_char[u.char_storage], u.insert_length);
22322 s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
22323 }
22324 state->cursor = (short)(u.where + u.insert_length);
22325
22326 s->undo_point--;
22327 s->redo_point--;
22328}
22329NK_API void
22330nk_textedit_redo(struct nk_text_edit *state)
22331{
22332 struct nk_text_undo_state *s = &state->undo;
22333 struct nk_text_undo_record *u, r;
22335 return;
22336
22337 /* we need to do two things: apply the redo record, and create an undo record */
22338 u = &s->undo_rec[s->undo_point];
22339 r = s->undo_rec[s->redo_point];
22340
22341 /* we KNOW there must be room for the undo record, because the redo record
22342 was derived from an undo record */
22345 u->where = r.where;
22346 u->char_storage = -1;
22347
22348 if (r.delete_length) {
22349 /* the redo record requires us to delete characters, so the undo record
22350 needs to store the characters */
22352 u->insert_length = 0;
22353 u->delete_length = 0;
22354 } else {
22355 int i;
22357 s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
22358
22359 /* now save the characters */
22360 for (i=0; i < u->insert_length; ++i) {
22361 s->undo_char[u->char_storage + i] =
22362 nk_str_rune_at(&state->string, u->where + i);
22363 }
22364 }
22366 }
22367
22368 if (r.insert_length) {
22369 /* easy case: need to insert n characters */
22372 }
22373 state->cursor = r.where + r.insert_length;
22374
22375 s->undo_point++;
22376 s->redo_point++;
22377}
22378NK_INTERN void
22379nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
22380{
22381 nk_textedit_createundo(&state->undo, where, 0, length);
22382}
22383NK_INTERN void
22384nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
22385{
22386 int i;
22387 nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
22388 if (p) {
22389 for (i=0; i < length; ++i)
22390 p[i] = nk_str_rune_at(&state->string, where+i);
22391 }
22392}
22393NK_INTERN void
22394nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
22395 int old_length, int new_length)
22396{
22397 int i;
22398 nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
22399 if (p) {
22400 for (i=0; i < old_length; ++i)
22401 p[i] = nk_str_rune_at(&state->string, where+i);
22402 }
22403}
22404NK_LIB void
22405nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
22406 nk_plugin_filter filter)
22407{
22408 /* reset the state to default */
22409 state->undo.undo_point = 0;
22410 state->undo.undo_char_point = 0;
22413 state->select_end = state->select_start = 0;
22414 state->cursor = 0;
22415 state->has_preferred_x = 0;
22416 state->preferred_x = 0;
22417 state->cursor_at_end_of_line = 0;
22418 state->initialized = 1;
22419 state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
22421 state->filter = filter;
22422 state->scrollbar = nk_vec2(0,0);
22423}
22424NK_API void
22425nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
22426{
22427 NK_ASSERT(state);
22428 NK_ASSERT(memory);
22429 if (!state || !memory || !size) return;
22430 NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
22431 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
22432 nk_str_init_fixed(&state->string, memory, size);
22433}
22434NK_API void
22435nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
22436{
22437 NK_ASSERT(state);
22438 NK_ASSERT(alloc);
22439 if (!state || !alloc) return;
22440 NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
22441 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
22442 nk_str_init(&state->string, alloc, size);
22443}
22444#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
22445NK_API void
22446nk_textedit_init_default(struct nk_text_edit *state)
22447{
22448 NK_ASSERT(state);
22449 if (!state) return;
22450 NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
22451 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
22452 nk_str_init_default(&state->string);
22453}
22454#endif
22455NK_API void
22457{
22458 NK_ASSERT(state);
22459 state->select_start = 0;
22460 state->select_end = state->string.len;
22461}
22462NK_API void
22463nk_textedit_free(struct nk_text_edit *state)
22464{
22465 NK_ASSERT(state);
22466 if (!state) return;
22467 nk_str_free(&state->string);
22468}
22469
22470
22471
22472
22473/* ===============================================================
22474 *
22475 * FILTER
22476 *
22477 * ===============================================================*/
22478NK_API int
22479nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
22480{
22481 NK_UNUSED(unicode);
22482 NK_UNUSED(box);
22483 return nk_true;
22484}
22485NK_API int
22486nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
22487{
22488 NK_UNUSED(box);
22489 if (unicode > 128) return nk_false;
22490 else return nk_true;
22491}
22492NK_API int
22493nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
22494{
22495 NK_UNUSED(box);
22496 if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
22497 return nk_false;
22498 else return nk_true;
22499}
22500NK_API int
22501nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
22502{
22503 NK_UNUSED(box);
22504 if ((unicode < '0' || unicode > '9') && unicode != '-')
22505 return nk_false;
22506 else return nk_true;
22507}
22508NK_API int
22509nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
22510{
22511 NK_UNUSED(box);
22512 if ((unicode < '0' || unicode > '9') &&
22513 (unicode < 'a' || unicode > 'f') &&
22514 (unicode < 'A' || unicode > 'F'))
22515 return nk_false;
22516 else return nk_true;
22517}
22518NK_API int
22519nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
22520{
22521 NK_UNUSED(box);
22522 if (unicode < '0' || unicode > '7')
22523 return nk_false;
22524 else return nk_true;
22525}
22526NK_API int
22527nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
22528{
22529 NK_UNUSED(box);
22530 if (unicode != '0' && unicode != '1')
22531 return nk_false;
22532 else return nk_true;
22533}
22534
22535/* ===============================================================
22536 *
22537 * EDIT
22538 *
22539 * ===============================================================*/
22540NK_LIB void
22541nk_edit_draw_text(struct nk_command_buffer *out,
22542 const struct nk_style_edit *style, float pos_x, float pos_y,
22543 float x_offset, const char *text, int byte_len, float row_height,
22544 const struct nk_user_font *font, struct nk_color background,
22545 struct nk_color foreground, int is_selected)
22546{
22547 NK_ASSERT(out);
22548 NK_ASSERT(font);
22549 NK_ASSERT(style);
22550 if (!text || !byte_len || !out || !style) return;
22551
22552 {int glyph_len = 0;
22553 nk_rune unicode = 0;
22554 int text_len = 0;
22555 float line_width = 0;
22556 float glyph_width;
22557 const char *line = text;
22558 float line_offset = 0;
22559 int line_count = 0;
22560
22561 struct nk_text txt;
22562 txt.padding = nk_vec2(0,0);
22563 txt.background = background;
22564 txt.text = foreground;
22565
22566 glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
22567 if (!glyph_len) return;
22568 while ((text_len < byte_len) && glyph_len)
22569 {
22570 if (unicode == '\n') {
22571 /* new line separator so draw previous line */
22572 struct nk_rect label;
22573 label.y = pos_y + line_offset;
22574 label.h = row_height;
22575 label.w = line_width;
22576 label.x = pos_x;
22577 if (!line_count)
22578 label.x += x_offset;
22579
22580 if (is_selected) /* selection needs to draw different background color */
22581 nk_fill_rect(out, label, 0, background);
22582 nk_widget_text(out, label, line, (int)((text + text_len) - line),
22583 &txt, NK_TEXT_CENTERED, font);
22584
22585 text_len++;
22586 line_count++;
22587 line_width = 0;
22588 line = text + text_len;
22589 line_offset += row_height;
22590 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
22591 continue;
22592 }
22593 if (unicode == '\r') {
22594 text_len++;
22595 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
22596 continue;
22597 }
22598 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
22599 line_width += (float)glyph_width;
22600 text_len += glyph_len;
22601 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
22602 continue;
22603 }
22604 if (line_width > 0) {
22605 /* draw last line */
22606 struct nk_rect label;
22607 label.y = pos_y + line_offset;
22608 label.h = row_height;
22609 label.w = line_width;
22610 label.x = pos_x;
22611 if (!line_count)
22612 label.x += x_offset;
22613
22614 if (is_selected)
22615 nk_fill_rect(out, label, 0, background);
22616 nk_widget_text(out, label, line, (int)((text + text_len) - line),
22617 &txt, NK_TEXT_LEFT, font);
22618 }}
22619}
22621nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
22622 struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
22623 struct nk_text_edit *edit, const struct nk_style_edit *style,
22624 struct nk_input *in, const struct nk_user_font *font)
22625{
22626 struct nk_rect area;
22627 nk_flags ret = 0;
22628 float row_height;
22629 char prev_state = 0;
22630 char is_hovered = 0;
22631 char select_all = 0;
22632 char cursor_follow = 0;
22633 struct nk_rect old_clip;
22634 struct nk_rect clip;
22635
22636 NK_ASSERT(state);
22637 NK_ASSERT(out);
22638 NK_ASSERT(style);
22639 if (!state || !out || !style)
22640 return ret;
22641
22642 /* visible text area calculation */
22643 area.x = bounds.x + style->padding.x + style->border;
22644 area.y = bounds.y + style->padding.y + style->border;
22645 area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
22646 area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
22647 if (flags & NK_EDIT_MULTILINE)
22648 area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
22649 row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
22650
22651 /* calculate clipping rectangle */
22652 old_clip = out->clip;
22653 nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
22654
22655 /* update edit state */
22656 prev_state = (char)edit->active;
22657 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
22659 edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
22660 bounds.x, bounds.y, bounds.w, bounds.h);
22661 }
22662
22663 /* (de)activate text editor */
22664 if (!prev_state && edit->active) {
22665 const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
22667 nk_textedit_clear_state(edit, type, filter);
22668 if (flags & NK_EDIT_AUTO_SELECT)
22669 select_all = nk_true;
22670 if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
22671 edit->cursor = edit->string.len;
22672 in = 0;
22673 }
22674 } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
22675 if (flags & NK_EDIT_READ_ONLY)
22677 else if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
22679
22680 ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
22681 if (prev_state != edit->active)
22683
22684 /* handle user input */
22685 if (edit->active && in)
22686 {
22687 int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
22688 const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
22689 const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
22690
22691 /* mouse click handler */
22692 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
22693 if (select_all) {
22695 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
22697 nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
22698 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
22699 (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
22700 nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
22701 cursor_follow = nk_true;
22702 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
22704 nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
22705 nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
22706 cursor_follow = nk_true;
22707 }
22708
22709 {int i; /* keyboard input */
22710 int old_mode = edit->mode;
22711 for (i = 0; i < NK_KEY_MAX; ++i) {
22712 if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
22713 if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
22714 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
22715 cursor_follow = nk_true;
22716 }
22717 }
22718 if (old_mode != edit->mode) {
22719 in->keyboard.text_len = 0;
22720 }}
22721
22722 /* text input */
22723 edit->filter = filter;
22724 if (in->keyboard.text_len) {
22726 cursor_follow = nk_true;
22727 in->keyboard.text_len = 0;
22728 }
22729
22730 /* enter key handler */
22732 cursor_follow = nk_true;
22733 if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
22734 nk_textedit_text(edit, "\n", 1);
22735 else if (flags & NK_EDIT_SIG_ENTER)
22736 ret |= NK_EDIT_COMMITED;
22737 else nk_textedit_text(edit, "\n", 1);
22738 }
22739
22740 /* cut & copy handler */
22741 {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
22742 int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
22743 if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
22744 {
22745 int glyph_len;
22746 nk_rune unicode;
22747 const char *text;
22748 int b = edit->select_start;
22749 int e = edit->select_end;
22750
22751 int begin = NK_MIN(b, e);
22752 int end = NK_MAX(b, e);
22753 text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
22754 if (edit->clip.copy)
22755 edit->clip.copy(edit->clip.userdata, text, end - begin);
22756 if (cut && !(flags & NK_EDIT_READ_ONLY)){
22757 nk_textedit_cut(edit);
22758 cursor_follow = nk_true;
22759 }
22760 }}
22761
22762 /* paste handler */
22763 {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
22764 if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
22765 edit->clip.paste(edit->clip.userdata, edit);
22766 cursor_follow = nk_true;
22767 }}
22768
22769 /* tab handler */
22770 {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
22771 if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
22772 nk_textedit_text(edit, " ", 4);
22773 cursor_follow = nk_true;
22774 }}
22775 }
22776
22777 /* set widget state */
22778 if (edit->active)
22779 *state = NK_WIDGET_STATE_ACTIVE;
22780 else nk_widget_state_reset(state);
22781
22782 if (is_hovered)
22783 *state |= NK_WIDGET_STATE_HOVERED;
22784
22785 /* DRAW EDIT */
22786 {const char *text = nk_str_get_const(&edit->string);
22787 int len = nk_str_len_char(&edit->string);
22788
22789 {/* select background colors/images */
22790 const struct nk_style_item *background;
22791 if (*state & NK_WIDGET_STATE_ACTIVED)
22792 background = &style->active;
22793 else if (*state & NK_WIDGET_STATE_HOVER)
22794 background = &style->hover;
22795 else background = &style->normal;
22796
22797 /* draw background frame */
22798 if (background->type == NK_STYLE_ITEM_COLOR) {
22799 nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
22800 nk_fill_rect(out, bounds, style->rounding, background->data.color);
22801 } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
22802
22803 area.w = NK_MAX(0, area.w - style->cursor_size);
22804 if (edit->active)
22805 {
22806 int total_lines = 1;
22807 struct nk_vec2 text_size = nk_vec2(0,0);
22808
22809 /* text pointer positions */
22810 const char *cursor_ptr = 0;
22811 const char *select_begin_ptr = 0;
22812 const char *select_end_ptr = 0;
22813
22814 /* 2D pixel positions */
22815 struct nk_vec2 cursor_pos = nk_vec2(0,0);
22816 struct nk_vec2 selection_offset_start = nk_vec2(0,0);
22817 struct nk_vec2 selection_offset_end = nk_vec2(0,0);
22818
22819 int selection_begin = NK_MIN(edit->select_start, edit->select_end);
22820 int selection_end = NK_MAX(edit->select_start, edit->select_end);
22821
22822 /* calculate total line count + total space + cursor/selection position */
22823 float line_width = 0.0f;
22824 if (text && len)
22825 {
22826 /* utf8 encoding */
22827 float glyph_width;
22828 int glyph_len = 0;
22829 nk_rune unicode = 0;
22830 int text_len = 0;
22831 int glyphs = 0;
22832 int row_begin = 0;
22833
22834 glyph_len = nk_utf_decode(text, &unicode, len);
22835 glyph_width = font->width(font->userdata, font->height, text, glyph_len);
22836 line_width = 0;
22837
22838 /* iterate all lines */
22839 while ((text_len < len) && glyph_len)
22840 {
22841 /* set cursor 2D position and line */
22842 if (!cursor_ptr && glyphs == edit->cursor)
22843 {
22844 int glyph_offset;
22845 struct nk_vec2 out_offset;
22846 struct nk_vec2 row_size;
22847 const char *remaining;
22848
22849 /* calculate 2d position */
22850 cursor_pos.y = (float)(total_lines-1) * row_height;
22851 row_size = nk_text_calculate_text_bounds(font, text+row_begin,
22852 text_len-row_begin, row_height, &remaining,
22853 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
22854 cursor_pos.x = row_size.x;
22855 cursor_ptr = text + text_len;
22856 }
22857
22858 /* set start selection 2D position and line */
22859 if (!select_begin_ptr && edit->select_start != edit->select_end &&
22860 glyphs == selection_begin)
22861 {
22862 int glyph_offset;
22863 struct nk_vec2 out_offset;
22864 struct nk_vec2 row_size;
22865 const char *remaining;
22866
22867 /* calculate 2d position */
22868 selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
22869 row_size = nk_text_calculate_text_bounds(font, text+row_begin,
22870 text_len-row_begin, row_height, &remaining,
22871 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
22872 selection_offset_start.x = row_size.x;
22873 select_begin_ptr = text + text_len;
22874 }
22875
22876 /* set end selection 2D position and line */
22877 if (!select_end_ptr && edit->select_start != edit->select_end &&
22878 glyphs == selection_end)
22879 {
22880 int glyph_offset;
22881 struct nk_vec2 out_offset;
22882 struct nk_vec2 row_size;
22883 const char *remaining;
22884
22885 /* calculate 2d position */
22886 selection_offset_end.y = (float)(total_lines-1) * row_height;
22887 row_size = nk_text_calculate_text_bounds(font, text+row_begin,
22888 text_len-row_begin, row_height, &remaining,
22889 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
22890 selection_offset_end.x = row_size.x;
22891 select_end_ptr = text + text_len;
22892 }
22893 if (unicode == '\n') {
22894 text_size.x = NK_MAX(text_size.x, line_width);
22895 total_lines++;
22896 line_width = 0;
22897 text_len++;
22898 glyphs++;
22899 row_begin = text_len;
22900 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
22901 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
22902 continue;
22903 }
22904
22905 glyphs++;
22906 text_len += glyph_len;
22907 line_width += (float)glyph_width;
22908
22909 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
22910 glyph_width = font->width(font->userdata, font->height,
22911 text+text_len, glyph_len);
22912 continue;
22913 }
22914 text_size.y = (float)total_lines * row_height;
22915
22916 /* handle case when cursor is at end of text buffer */
22917 if (!cursor_ptr && edit->cursor == edit->string.len) {
22918 cursor_pos.x = line_width;
22919 cursor_pos.y = text_size.y - row_height;
22920 }
22921 }
22922 {
22923 /* scrollbar */
22924 if (cursor_follow)
22925 {
22926 /* update scrollbar to follow cursor */
22927 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
22928 /* horizontal scroll */
22929 const float scroll_increment = area.w * 0.25f;
22930 if (cursor_pos.x < edit->scrollbar.x)
22931 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
22932 if (cursor_pos.x >= edit->scrollbar.x + area.w)
22933 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, edit->scrollbar.x + scroll_increment);
22934 } else edit->scrollbar.x = 0;
22935
22936 if (flags & NK_EDIT_MULTILINE) {
22937 /* vertical scroll */
22938 if (cursor_pos.y < edit->scrollbar.y)
22939 edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
22940 if (cursor_pos.y >= edit->scrollbar.y + area.h)
22941 edit->scrollbar.y = edit->scrollbar.y + row_height;
22942 } else edit->scrollbar.y = 0;
22943 }
22944
22945 /* scrollbar widget */
22946 if (flags & NK_EDIT_MULTILINE)
22947 {
22948 nk_flags ws;
22949 struct nk_rect scroll;
22950 float scroll_target;
22951 float scroll_offset;
22952 float scroll_step;
22953 float scroll_inc;
22954
22955 scroll = area;
22956 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
22957 scroll.w = style->scrollbar_size.x;
22958
22959 scroll_offset = edit->scrollbar.y;
22960 scroll_step = scroll.h * 0.10f;
22961 scroll_inc = scroll.h * 0.01f;
22962 scroll_target = text_size.y;
22963 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
22964 scroll_offset, scroll_target, scroll_step, scroll_inc,
22965 &style->scrollbar, in, font);
22966 }
22967 }
22968
22969 /* draw text */
22970 {struct nk_color background_color;
22971 struct nk_color text_color;
22972 struct nk_color sel_background_color;
22973 struct nk_color sel_text_color;
22974 struct nk_color cursor_color;
22975 struct nk_color cursor_text_color;
22976 const struct nk_style_item *background;
22977 nk_push_scissor(out, clip);
22978
22979 /* select correct colors to draw */
22980 if (*state & NK_WIDGET_STATE_ACTIVED) {
22981 background = &style->active;
22982 text_color = style->text_active;
22983 sel_text_color = style->selected_text_hover;
22984 sel_background_color = style->selected_hover;
22985 cursor_color = style->cursor_hover;
22986 cursor_text_color = style->cursor_text_hover;
22987 } else if (*state & NK_WIDGET_STATE_HOVER) {
22988 background = &style->hover;
22989 text_color = style->text_hover;
22990 sel_text_color = style->selected_text_hover;
22991 sel_background_color = style->selected_hover;
22992 cursor_text_color = style->cursor_text_hover;
22993 cursor_color = style->cursor_hover;
22994 } else {
22995 background = &style->normal;
22996 text_color = style->text_normal;
22997 sel_text_color = style->selected_text_normal;
22998 sel_background_color = style->selected_normal;
22999 cursor_color = style->cursor_normal;
23000 cursor_text_color = style->cursor_text_normal;
23001 }
23002 if (background->type == NK_STYLE_ITEM_IMAGE)
23003 background_color = nk_rgba(0,0,0,0);
23004 else background_color = background->data.color;
23005
23006
23007 if (edit->select_start == edit->select_end) {
23008 /* no selection so just draw the complete text */
23009 const char *begin = nk_str_get_const(&edit->string);
23010 int l = nk_str_len_char(&edit->string);
23011 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
23012 area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
23013 background_color, text_color, nk_false);
23014 } else {
23015 /* edit has selection so draw 1-3 text chunks */
23016 if (edit->select_start != edit->select_end && selection_begin > 0){
23017 /* draw unselected text before selection */
23018 const char *begin = nk_str_get_const(&edit->string);
23019 NK_ASSERT(select_begin_ptr);
23020 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
23021 area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
23022 row_height, font, background_color, text_color, nk_false);
23023 }
23024 if (edit->select_start != edit->select_end) {
23025 /* draw selected text */
23026 NK_ASSERT(select_begin_ptr);
23027 if (!select_end_ptr) {
23028 const char *begin = nk_str_get_const(&edit->string);
23029 select_end_ptr = begin + nk_str_len_char(&edit->string);
23030 }
23031 nk_edit_draw_text(out, style,
23032 area.x - edit->scrollbar.x,
23033 area.y + selection_offset_start.y - edit->scrollbar.y,
23034 selection_offset_start.x,
23035 select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
23036 row_height, font, sel_background_color, sel_text_color, nk_true);
23037 }
23038 if ((edit->select_start != edit->select_end &&
23039 selection_end < edit->string.len))
23040 {
23041 /* draw unselected text after selected text */
23042 const char *begin = select_end_ptr;
23043 const char *end = nk_str_get_const(&edit->string) +
23044 nk_str_len_char(&edit->string);
23045 NK_ASSERT(select_end_ptr);
23046 nk_edit_draw_text(out, style,
23047 area.x - edit->scrollbar.x,
23048 area.y + selection_offset_end.y - edit->scrollbar.y,
23049 selection_offset_end.x,
23050 begin, (int)(end - begin), row_height, font,
23051 background_color, text_color, nk_true);
23052 }
23053 }
23054
23055 /* cursor */
23056 if (edit->select_start == edit->select_end)
23057 {
23058 if (edit->cursor >= nk_str_len(&edit->string) ||
23059 (cursor_ptr && *cursor_ptr == '\n')) {
23060 /* draw cursor at end of line */
23061 struct nk_rect cursor;
23062 cursor.w = style->cursor_size;
23063 cursor.h = font->height;
23064 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
23065 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
23066 cursor.y -= edit->scrollbar.y;
23067 nk_fill_rect(out, cursor, 0, cursor_color);
23068 } else {
23069 /* draw cursor inside text */
23070 int glyph_len;
23071 struct nk_rect label;
23072 struct nk_text txt;
23073
23074 nk_rune unicode;
23075 NK_ASSERT(cursor_ptr);
23076 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
23077
23078 label.x = area.x + cursor_pos.x - edit->scrollbar.x;
23079 label.y = area.y + cursor_pos.y - edit->scrollbar.y;
23080 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
23081 label.h = row_height;
23082
23083 txt.padding = nk_vec2(0,0);
23084 txt.background = cursor_color;;
23085 txt.text = cursor_text_color;
23086 nk_fill_rect(out, label, 0, cursor_color);
23087 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
23088 }
23089 }}
23090 } else {
23091 /* not active so just draw text */
23092 int l = nk_str_len_char(&edit->string);
23093 const char *begin = nk_str_get_const(&edit->string);
23094
23095 const struct nk_style_item *background;
23096 struct nk_color background_color;
23097 struct nk_color text_color;
23098 nk_push_scissor(out, clip);
23099 if (*state & NK_WIDGET_STATE_ACTIVED) {
23100 background = &style->active;
23101 text_color = style->text_active;
23102 } else if (*state & NK_WIDGET_STATE_HOVER) {
23103 background = &style->hover;
23104 text_color = style->text_hover;
23105 } else {
23106 background = &style->normal;
23107 text_color = style->text_normal;
23108 }
23109 if (background->type == NK_STYLE_ITEM_IMAGE)
23110 background_color = nk_rgba(0,0,0,0);
23111 else background_color = background->data.color;
23112 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
23113 area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
23114 background_color, text_color, nk_false);
23115 }
23116 nk_push_scissor(out, old_clip);}
23117 return ret;
23118}
23119NK_API void
23120nk_edit_focus(struct nk_context *ctx, nk_flags flags)
23121{
23122 nk_hash hash;
23123 struct nk_window *win;
23124
23125 NK_ASSERT(ctx);
23126 NK_ASSERT(ctx->current);
23127 if (!ctx || !ctx->current) return;
23128
23129 win = ctx->current;
23130 hash = win->edit.seq;
23131 win->edit.active = nk_true;
23132 win->edit.name = hash;
23135}
23136NK_API void
23137nk_edit_unfocus(struct nk_context *ctx)
23138{
23139 struct nk_window *win;
23140 NK_ASSERT(ctx);
23141 NK_ASSERT(ctx->current);
23142 if (!ctx || !ctx->current) return;
23143
23144 win = ctx->current;
23145 win->edit.active = nk_false;
23146 win->edit.name = 0;
23147}
23150 char *memory, int *len, int max, nk_plugin_filter filter)
23151{
23152 nk_hash hash;
23153 nk_flags state;
23154 struct nk_text_edit *edit;
23155 struct nk_window *win;
23156
23157 NK_ASSERT(ctx);
23158 NK_ASSERT(memory);
23159 NK_ASSERT(len);
23160 if (!ctx || !memory || !len)
23161 return 0;
23162
23163 filter = (!filter) ? nk_filter_default: filter;
23164 win = ctx->current;
23165 hash = win->edit.seq;
23166 edit = &ctx->text_edit;
23167 nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
23169
23170 if (win->edit.active && hash == win->edit.name) {
23172 edit->cursor = nk_utf_len(memory, *len);
23173 else edit->cursor = win->edit.cursor;
23174 if (!(flags & NK_EDIT_SELECTABLE)) {
23175 edit->select_start = win->edit.cursor;
23176 edit->select_end = win->edit.cursor;
23177 } else {
23178 edit->select_start = win->edit.sel_start;
23179 edit->select_end = win->edit.sel_end;
23180 }
23181 edit->mode = win->edit.mode;
23182 edit->scrollbar.x = (float)win->edit.scrollbar.x;
23183 edit->scrollbar.y = (float)win->edit.scrollbar.y;
23184 edit->active = nk_true;
23185 } else edit->active = nk_false;
23186
23187 max = NK_MAX(1, max);
23188 *len = NK_MIN(*len, max-1);
23189 nk_str_init_fixed(&edit->string, memory, (nk_size)max);
23190 edit->string.buffer.allocated = (nk_size)*len;
23191 edit->string.len = nk_utf_len(memory, *len);
23192 state = nk_edit_buffer(ctx, flags, edit, filter);
23193 *len = (int)edit->string.buffer.allocated;
23194
23195 if (edit->active) {
23196 win->edit.cursor = edit->cursor;
23197 win->edit.sel_start = edit->select_start;
23198 win->edit.sel_end = edit->select_end;
23199 win->edit.mode = edit->mode;
23202 } return state;
23203}
23206 struct nk_text_edit *edit, nk_plugin_filter filter)
23207{
23208 struct nk_window *win;
23209 struct nk_style *style;
23210 struct nk_input *in;
23211
23212 enum nk_widget_layout_states state;
23213 struct nk_rect bounds;
23214
23215 nk_flags ret_flags = 0;
23216 unsigned char prev_state;
23217 nk_hash hash;
23218
23219 /* make sure correct values */
23220 NK_ASSERT(ctx);
23221 NK_ASSERT(edit);
23222 NK_ASSERT(ctx->current);
23223 NK_ASSERT(ctx->current->layout);
23224 if (!ctx || !ctx->current || !ctx->current->layout)
23225 return 0;
23226
23227 win = ctx->current;
23228 style = &ctx->style;
23229 state = nk_widget(&bounds, ctx);
23230 if (!state) return state;
23231 in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23232
23233 /* check if edit is currently hot item */
23234 hash = win->edit.seq++;
23235 if (win->edit.active && hash == win->edit.name) {
23236 if (flags & NK_EDIT_NO_CURSOR)
23237 edit->cursor = edit->string.len;
23238 if (!(flags & NK_EDIT_SELECTABLE)) {
23239 edit->select_start = edit->cursor;
23240 edit->select_end = edit->cursor;
23241 }
23242 if (flags & NK_EDIT_CLIPBOARD)
23243 edit->clip = ctx->clip;
23244 edit->active = (unsigned char)win->edit.active;
23245 } else edit->active = nk_false;
23246 edit->mode = win->edit.mode;
23247
23248 filter = (!filter) ? nk_filter_default: filter;
23249 prev_state = (unsigned char)edit->active;
23250 in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
23251 ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
23252 filter, edit, &style->edit, in, style->font);
23253
23256 if (edit->active && prev_state != edit->active) {
23257 /* current edit is now hot */
23258 win->edit.active = nk_true;
23259 win->edit.name = hash;
23260 } else if (prev_state && !edit->active) {
23261 /* current edit is now cold */
23262 win->edit.active = nk_false;
23263 } return ret_flags;
23264}
23267 char *buffer, int max, nk_plugin_filter filter)
23268{
23269 nk_flags result;
23270 int len = nk_strlen(buffer);
23271 result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
23272 buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
23273 return result;
23274}
23275
23276
23277
23278
23279/* ===============================================================
23280 *
23281 * PROPERTY
23282 *
23283 * ===============================================================*/
23284NK_LIB void
23285nk_drag_behavior(nk_flags *state, const struct nk_input *in,
23286 struct nk_rect drag, struct nk_property_variant *variant,
23287 float inc_per_pixel)
23288{
23289 int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
23290 int left_mouse_click_in_cursor = in &&
23292
23293 nk_widget_state_reset(state);
23294 if (nk_input_is_mouse_hovering_rect(in, drag))
23295 *state = NK_WIDGET_STATE_HOVERED;
23296
23297 if (left_mouse_down && left_mouse_click_in_cursor) {
23298 float delta, pixels;
23299 pixels = in->mouse.delta.x;
23300 delta = pixels * inc_per_pixel;
23301 switch (variant->kind) {
23302 default: break;
23303 case NK_PROPERTY_INT:
23304 variant->value.i = variant->value.i + (int)delta;
23305 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
23306 break;
23307 case NK_PROPERTY_FLOAT:
23308 variant->value.f = variant->value.f + (float)delta;
23309 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
23310 break;
23311 case NK_PROPERTY_DOUBLE:
23312 variant->value.d = variant->value.d + (double)delta;
23313 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
23314 break;
23315 }
23316 *state = NK_WIDGET_STATE_ACTIVE;
23317 }
23319 *state |= NK_WIDGET_STATE_ENTERED;
23320 else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
23321 *state |= NK_WIDGET_STATE_LEFT;
23322}
23323NK_LIB void
23324nk_property_behavior(nk_flags *ws, const struct nk_input *in,
23325 struct nk_rect property, struct nk_rect label, struct nk_rect edit,
23326 struct nk_rect empty, int *state, struct nk_property_variant *variant,
23327 float inc_per_pixel)
23328{
23329 if (in && *state == NK_PROPERTY_DEFAULT) {
23330 if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
23331 *state = NK_PROPERTY_EDIT;
23333 *state = NK_PROPERTY_DRAG;
23335 *state = NK_PROPERTY_DRAG;
23336 }
23337 if (*state == NK_PROPERTY_DRAG) {
23338 nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
23339 if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
23340 }
23341}
23342NK_LIB void
23343nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
23344 const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
23345 const char *name, int len, const struct nk_user_font *font)
23346{
23347 struct nk_text text;
23348 const struct nk_style_item *background;
23349
23350 /* select correct background and text color */
23351 if (state & NK_WIDGET_STATE_ACTIVED) {
23352 background = &style->active;
23353 text.text = style->label_active;
23354 } else if (state & NK_WIDGET_STATE_HOVER) {
23355 background = &style->hover;
23356 text.text = style->label_hover;
23357 } else {
23358 background = &style->normal;
23359 text.text = style->label_normal;
23360 }
23361
23362 /* draw background */
23363 if (background->type == NK_STYLE_ITEM_IMAGE) {
23364 nk_draw_image(out, *bounds, &background->data.image, nk_white);
23365 text.background = nk_rgba(0,0,0,0);
23366 } else {
23367 text.background = background->data.color;
23368 nk_fill_rect(out, *bounds, style->rounding, background->data.color);
23369 nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
23370 }
23371
23372 /* draw label */
23373 text.padding = nk_vec2(0,0);
23374 nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
23375}
23376NK_LIB void
23377nk_do_property(nk_flags *ws,
23378 struct nk_command_buffer *out, struct nk_rect property,
23379 const char *name, struct nk_property_variant *variant,
23380 float inc_per_pixel, char *buffer, int *len,
23381 int *state, int *cursor, int *select_begin, int *select_end,
23382 const struct nk_style_property *style,
23383 enum nk_property_filter filter, struct nk_input *in,
23384 const struct nk_user_font *font, struct nk_text_edit *text_edit,
23385 enum nk_button_behavior behavior)
23386{
23387 const nk_plugin_filter filters[] = {
23390 };
23391 int active, old;
23392 int num_len, name_len;
23393 char string[NK_MAX_NUMBER_BUFFER];
23394 float size;
23395
23396 char *dst = 0;
23397 int *length;
23398
23399 struct nk_rect left;
23400 struct nk_rect right;
23401 struct nk_rect label;
23402 struct nk_rect edit;
23403 struct nk_rect empty;
23404
23405 /* left decrement button */
23406 left.h = font->height/2;
23407 left.w = left.h;
23408 left.x = property.x + style->border + style->padding.x;
23409 left.y = property.y + style->border + property.h/2.0f - left.h/2;
23410
23411 /* text label */
23412 name_len = nk_strlen(name);
23413 size = font->width(font->userdata, font->height, name, name_len);
23414 label.x = left.x + left.w + style->padding.x;
23415 label.w = (float)size + 2 * style->padding.x;
23416 label.y = property.y + style->border + style->padding.y;
23417 label.h = property.h - (2 * style->border + 2 * style->padding.y);
23418
23419 /* right increment button */
23420 right.y = left.y;
23421 right.w = left.w;
23422 right.h = left.h;
23423 right.x = property.x + property.w - (right.w + style->padding.x);
23424
23425 /* edit */
23426 if (*state == NK_PROPERTY_EDIT) {
23427 size = font->width(font->userdata, font->height, buffer, *len);
23428 size += style->edit.cursor_size;
23429 length = len;
23430 dst = buffer;
23431 } else {
23432 switch (variant->kind) {
23433 default: break;
23434 case NK_PROPERTY_INT:
23435 nk_itoa(string, variant->value.i);
23436 num_len = nk_strlen(string);
23437 break;
23438 case NK_PROPERTY_FLOAT:
23439 NK_DTOA(string, (double)variant->value.f);
23440 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
23441 break;
23442 case NK_PROPERTY_DOUBLE:
23443 NK_DTOA(string, variant->value.d);
23444 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
23445 break;
23446 }
23447 size = font->width(font->userdata, font->height, string, num_len);
23448 dst = string;
23449 length = &num_len;
23450 }
23451
23452 edit.w = (float)size + 2 * style->padding.x;
23453 edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
23454 edit.x = right.x - (edit.w + style->padding.x);
23455 edit.y = property.y + style->border;
23456 edit.h = property.h - (2 * style->border);
23457
23458 /* empty left space activator */
23459 empty.w = edit.x - (label.x + label.w);
23460 empty.x = label.x + label.w;
23461 empty.y = property.y;
23462 empty.h = property.h;
23463
23464 /* update property */
23465 old = (*state == NK_PROPERTY_EDIT);
23466 nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
23467
23468 /* draw property */
23469 if (style->draw_begin) style->draw_begin(out, style->userdata);
23470 nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
23471 if (style->draw_end) style->draw_end(out, style->userdata);
23472
23473 /* execute right button */
23474 if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
23475 switch (variant->kind) {
23476 default: break;
23477 case NK_PROPERTY_INT:
23478 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
23479 case NK_PROPERTY_FLOAT:
23480 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
23481 case NK_PROPERTY_DOUBLE:
23482 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
23483 }
23484 }
23485 /* execute left button */
23486 if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
23487 switch (variant->kind) {
23488 default: break;
23489 case NK_PROPERTY_INT:
23490 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
23491 case NK_PROPERTY_FLOAT:
23492 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
23493 case NK_PROPERTY_DOUBLE:
23494 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
23495 }
23496 }
23497 if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
23498 /* property has been activated so setup buffer */
23499 NK_MEMCPY(buffer, dst, (nk_size)*length);
23500 *cursor = nk_utf_len(buffer, *length);
23501 *len = *length;
23502 length = len;
23503 dst = buffer;
23504 active = 0;
23505 } else active = (*state == NK_PROPERTY_EDIT);
23506
23507 /* execute and run text edit field */
23508 nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
23509 text_edit->active = (unsigned char)active;
23510 text_edit->string.len = *length;
23511 text_edit->cursor = NK_CLAMP(0, *cursor, *length);
23512 text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
23513 text_edit->select_end = NK_CLAMP(0,*select_end, *length);
23514 text_edit->string.buffer.allocated = (nk_size)*length;
23516 text_edit->string.buffer.memory.ptr = dst;
23518 text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
23519 nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
23520 filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
23521
23522 *length = text_edit->string.len;
23523 *cursor = text_edit->cursor;
23524 *select_begin = text_edit->select_start;
23525 *select_end = text_edit->select_end;
23526 if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
23527 text_edit->active = nk_false;
23528
23529 if (active && !text_edit->active) {
23530 /* property is now not active so convert edit text to value*/
23531 *state = NK_PROPERTY_DEFAULT;
23532 buffer[*len] = '\0';
23533 switch (variant->kind) {
23534 default: break;
23535 case NK_PROPERTY_INT:
23536 variant->value.i = nk_strtoi(buffer, 0);
23537 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
23538 break;
23539 case NK_PROPERTY_FLOAT:
23540 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
23541 variant->value.f = nk_strtof(buffer, 0);
23542 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
23543 break;
23544 case NK_PROPERTY_DOUBLE:
23545 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
23546 variant->value.d = nk_strtod(buffer, 0);
23547 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
23548 break;
23549 }
23550 }
23551}
23552NK_LIB struct nk_property_variant
23553nk_property_variant_int(int value, int min_value, int max_value, int step)
23554{
23555 struct nk_property_variant result;
23556 result.kind = NK_PROPERTY_INT;
23557 result.value.i = value;
23558 result.min_value.i = min_value;
23559 result.max_value.i = max_value;
23560 result.step.i = step;
23561 return result;
23562}
23563NK_LIB struct nk_property_variant
23564nk_property_variant_float(float value, float min_value, float max_value, float step)
23565{
23566 struct nk_property_variant result;
23567 result.kind = NK_PROPERTY_FLOAT;
23568 result.value.f = value;
23569 result.min_value.f = min_value;
23570 result.max_value.f = max_value;
23571 result.step.f = step;
23572 return result;
23573}
23574NK_LIB struct nk_property_variant
23575nk_property_variant_double(double value, double min_value, double max_value,
23576 double step)
23577{
23578 struct nk_property_variant result;
23579 result.kind = NK_PROPERTY_DOUBLE;
23580 result.value.d = value;
23581 result.min_value.d = min_value;
23582 result.max_value.d = max_value;
23583 result.step.d = step;
23584 return result;
23585}
23586NK_LIB void
23587nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
23588 float inc_per_pixel, const enum nk_property_filter filter)
23589{
23590 struct nk_window *win;
23591 struct nk_panel *layout;
23592 struct nk_input *in;
23593 const struct nk_style *style;
23594
23595 struct nk_rect bounds;
23597
23598 int *state = 0;
23599 nk_hash hash = 0;
23600 char *buffer = 0;
23601 int *len = 0;
23602 int *cursor = 0;
23603 int *select_begin = 0;
23604 int *select_end = 0;
23605 int old_state;
23606
23607 char dummy_buffer[NK_MAX_NUMBER_BUFFER];
23608 int dummy_state = NK_PROPERTY_DEFAULT;
23609 int dummy_length = 0;
23610 int dummy_cursor = 0;
23611 int dummy_select_begin = 0;
23612 int dummy_select_end = 0;
23613
23614 NK_ASSERT(ctx);
23615 NK_ASSERT(ctx->current);
23616 NK_ASSERT(ctx->current->layout);
23617 if (!ctx || !ctx->current || !ctx->current->layout)
23618 return;
23619
23620 win = ctx->current;
23621 layout = win->layout;
23622 style = &ctx->style;
23623 s = nk_widget(&bounds, ctx);
23624 if (!s) return;
23625
23626 /* calculate hash from name */
23627 if (name[0] == '#') {
23628 hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
23629 name++; /* special number hash */
23630 } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
23631
23632 /* check if property is currently hot item */
23633 if (win->property.active && hash == win->property.name) {
23634 buffer = win->property.buffer;
23635 len = &win->property.length;
23636 cursor = &win->property.cursor;
23637 state = &win->property.state;
23638 select_begin = &win->property.select_start;
23639 select_end = &win->property.select_end;
23640 } else {
23641 buffer = dummy_buffer;
23642 len = &dummy_length;
23643 cursor = &dummy_cursor;
23644 state = &dummy_state;
23645 select_begin = &dummy_select_begin;
23646 select_end = &dummy_select_end;
23647 }
23648
23649 /* execute property widget */
23650 old_state = *state;
23651 ctx->text_edit.clip = ctx->clip;
23652 in = ((s == NK_WIDGET_ROM && !win->property.active) ||
23653 layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23654 nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
23655 variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
23656 select_end, &style->property, filter, in, style->font, &ctx->text_edit,
23657 ctx->button_behavior);
23658
23659 if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
23660 /* current property is now hot */
23661 win->property.active = 1;
23662 NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
23663 win->property.length = *len;
23664 win->property.cursor = *cursor;
23665 win->property.state = *state;
23666 win->property.name = hash;
23667 win->property.select_start = *select_begin;
23668 win->property.select_end = *select_end;
23669 if (*state == NK_PROPERTY_DRAG) {
23670 ctx->input.mouse.grab = nk_true;
23671 ctx->input.mouse.grabbed = nk_true;
23672 }
23673 }
23674 /* check if previously active property is now inactive */
23675 if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
23676 if (old_state == NK_PROPERTY_DRAG) {
23677 ctx->input.mouse.grab = nk_false;
23678 ctx->input.mouse.grabbed = nk_false;
23679 ctx->input.mouse.ungrab = nk_true;
23680 }
23681 win->property.select_start = 0;
23682 win->property.select_end = 0;
23683 win->property.active = 0;
23684 }
23685}
23686NK_API void
23687nk_property_int(struct nk_context *ctx, const char *name,
23688 int min, int *val, int max, int step, float inc_per_pixel)
23689{
23690 struct nk_property_variant variant;
23691 NK_ASSERT(ctx);
23692 NK_ASSERT(name);
23693 NK_ASSERT(val);
23694
23695 if (!ctx || !ctx->current || !name || !val) return;
23696 variant = nk_property_variant_int(*val, min, max, step);
23697 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
23698 *val = variant.value.i;
23699}
23700NK_API void
23701nk_property_float(struct nk_context *ctx, const char *name,
23702 float min, float *val, float max, float step, float inc_per_pixel)
23703{
23704 struct nk_property_variant variant;
23705 NK_ASSERT(ctx);
23706 NK_ASSERT(name);
23707 NK_ASSERT(val);
23708
23709 if (!ctx || !ctx->current || !name || !val) return;
23710 variant = nk_property_variant_float(*val, min, max, step);
23711 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23712 *val = variant.value.f;
23713}
23714NK_API void
23715nk_property_double(struct nk_context *ctx, const char *name,
23716 double min, double *val, double max, double step, float inc_per_pixel)
23717{
23718 struct nk_property_variant variant;
23719 NK_ASSERT(ctx);
23720 NK_ASSERT(name);
23721 NK_ASSERT(val);
23722
23723 if (!ctx || !ctx->current || !name || !val) return;
23724 variant = nk_property_variant_double(*val, min, max, step);
23725 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23726 *val = variant.value.d;
23727}
23728NK_API int
23729nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
23730 int max, int step, float inc_per_pixel)
23731{
23732 struct nk_property_variant variant;
23733 NK_ASSERT(ctx);
23734 NK_ASSERT(name);
23735
23736 if (!ctx || !ctx->current || !name) return val;
23737 variant = nk_property_variant_int(val, min, max, step);
23738 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
23739 val = variant.value.i;
23740 return val;
23741}
23742NK_API float
23743nk_propertyf(struct nk_context *ctx, const char *name, float min,
23744 float val, float max, float step, float inc_per_pixel)
23745{
23746 struct nk_property_variant variant;
23747 NK_ASSERT(ctx);
23748 NK_ASSERT(name);
23749
23750 if (!ctx || !ctx->current || !name) return val;
23751 variant = nk_property_variant_float(val, min, max, step);
23752 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23753 val = variant.value.f;
23754 return val;
23755}
23756NK_API double
23757nk_propertyd(struct nk_context *ctx, const char *name, double min,
23758 double val, double max, double step, float inc_per_pixel)
23759{
23760 struct nk_property_variant variant;
23761 NK_ASSERT(ctx);
23762 NK_ASSERT(name);
23763
23764 if (!ctx || !ctx->current || !name) return val;
23765 variant = nk_property_variant_double(val, min, max, step);
23766 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23767 val = variant.value.d;
23768 return val;
23769}
23770
23771
23772
23773
23774/* ==============================================================
23775 *
23776 * CHART
23777 *
23778 * ===============================================================*/
23779NK_API int
23780nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
23781 struct nk_color color, struct nk_color highlight,
23782 int count, float min_value, float max_value)
23783{
23784 struct nk_window *win;
23785 struct nk_chart *chart;
23786 const struct nk_style *config;
23787 const struct nk_style_chart *style;
23788
23789 const struct nk_style_item *background;
23790 struct nk_rect bounds = {0, 0, 0, 0};
23791
23792 NK_ASSERT(ctx);
23793 NK_ASSERT(ctx->current);
23794 NK_ASSERT(ctx->current->layout);
23795
23796 if (!ctx || !ctx->current || !ctx->current->layout) return 0;
23797 if (!nk_widget(&bounds, ctx)) {
23798 chart = &ctx->current->layout->chart;
23799 nk_zero(chart, sizeof(*chart));
23800 return 0;
23801 }
23802
23803 win = ctx->current;
23804 config = &ctx->style;
23805 chart = &win->layout->chart;
23806 style = &config->chart;
23807
23808 /* setup basic generic chart */
23809 nk_zero(chart, sizeof(*chart));
23810 chart->x = bounds.x + style->padding.x;
23811 chart->y = bounds.y + style->padding.y;
23812 chart->w = bounds.w - 2 * style->padding.x;
23813 chart->h = bounds.h - 2 * style->padding.y;
23814 chart->w = NK_MAX(chart->w, 2 * style->padding.x);
23815 chart->h = NK_MAX(chart->h, 2 * style->padding.y);
23816
23817 /* add first slot into chart */
23818 {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
23819 slot->type = type;
23820 slot->count = count;
23821 slot->color = color;
23822 slot->highlight = highlight;
23823 slot->min = NK_MIN(min_value, max_value);
23824 slot->max = NK_MAX(min_value, max_value);
23825 slot->range = slot->max - slot->min;}
23826
23827 /* draw chart background */
23828 background = &style->background;
23829 if (background->type == NK_STYLE_ITEM_IMAGE) {
23830 nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
23831 } else {
23832 nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
23833 nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
23834 style->rounding, style->background.data.color);
23835 }
23836 return 1;
23837}
23838NK_API int
23839nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
23840 int count, float min_value, float max_value)
23841{
23842 return nk_chart_begin_colored(ctx, type, ctx->style.chart.color,
23843 ctx->style.chart.selected_color, count, min_value, max_value);
23844}
23845NK_API void
23847 struct nk_color color, struct nk_color highlight,
23848 int count, float min_value, float max_value)
23849{
23850 NK_ASSERT(ctx);
23851 NK_ASSERT(ctx->current);
23852 NK_ASSERT(ctx->current->layout);
23853 NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
23854 if (!ctx || !ctx->current || !ctx->current->layout) return;
23855 if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
23856
23857 /* add another slot into the graph */
23858 {struct nk_chart *chart = &ctx->current->layout->chart;
23859 struct nk_chart_slot *slot = &chart->slots[chart->slot++];
23860 slot->type = type;
23861 slot->count = count;
23862 slot->color = color;
23863 slot->highlight = highlight;
23864 slot->min = NK_MIN(min_value, max_value);
23865 slot->max = NK_MAX(min_value, max_value);
23866 slot->range = slot->max - slot->min;}
23867}
23868NK_API void
23869nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
23870 int count, float min_value, float max_value)
23871{
23873 ctx->style.chart.selected_color, count, min_value, max_value);
23874}
23876nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
23877 struct nk_chart *g, float value, int slot)
23878{
23879 struct nk_panel *layout = win->layout;
23880 const struct nk_input *i = &ctx->input;
23881 struct nk_command_buffer *out = &win->buffer;
23882
23883 nk_flags ret = 0;
23884 struct nk_vec2 cur;
23885 struct nk_rect bounds;
23886 struct nk_color color;
23887 float step;
23888 float range;
23889 float ratio;
23890
23891 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
23892 step = g->w / (float)g->slots[slot].count;
23893 range = g->slots[slot].max - g->slots[slot].min;
23894 ratio = (value - g->slots[slot].min) / range;
23895
23896 if (g->slots[slot].index == 0) {
23897 /* first data point does not have a connection */
23898 g->slots[slot].last.x = g->x;
23899 g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
23900
23901 bounds.x = g->slots[slot].last.x - 2;
23902 bounds.y = g->slots[slot].last.y - 2;
23903 bounds.w = bounds.h = 4;
23904
23905 color = g->slots[slot].color;
23906 if (!(layout->flags & NK_WINDOW_ROM) &&
23907 NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
23909 ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
23911 color = g->slots[slot].highlight;
23912 }
23913 nk_fill_rect(out, bounds, 0, color);
23914 g->slots[slot].index += 1;
23915 return ret;
23916 }
23917
23918 /* draw a line between the last data point and the new one */
23919 color = g->slots[slot].color;
23920 cur.x = g->x + (float)(step * (float)g->slots[slot].index);
23921 cur.y = (g->y + g->h) - (ratio * (float)g->h);
23922 nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
23923
23924 bounds.x = cur.x - 3;
23925 bounds.y = cur.y - 3;
23926 bounds.w = bounds.h = 6;
23927
23928 /* user selection of current data point */
23929 if (!(layout->flags & NK_WINDOW_ROM)) {
23930 if (nk_input_is_mouse_hovering_rect(i, bounds)) {
23931 ret = NK_CHART_HOVERING;
23932 ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
23934 color = g->slots[slot].highlight;
23935 }
23936 }
23937 nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
23938
23939 /* save current data point position */
23940 g->slots[slot].last.x = cur.x;
23941 g->slots[slot].last.y = cur.y;
23942 g->slots[slot].index += 1;
23943 return ret;
23944}
23946nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
23947 struct nk_chart *chart, float value, int slot)
23948{
23949 struct nk_command_buffer *out = &win->buffer;
23950 const struct nk_input *in = &ctx->input;
23951 struct nk_panel *layout = win->layout;
23952
23953 float ratio;
23954 nk_flags ret = 0;
23955 struct nk_color color;
23956 struct nk_rect item = {0,0,0,0};
23957
23958 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
23959 if (chart->slots[slot].index >= chart->slots[slot].count)
23960 return nk_false;
23961 if (chart->slots[slot].count) {
23962 float padding = (float)(chart->slots[slot].count-1);
23963 item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
23964 }
23965
23966 /* calculate bounds of current bar chart entry */
23967 color = chart->slots[slot].color;;
23968 item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
23969 if (value >= 0) {
23970 ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
23971 item.y = (chart->y + chart->h) - chart->h * ratio;
23972 } else {
23973 ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
23974 item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
23975 }
23976 item.x = chart->x + ((float)chart->slots[slot].index * item.w);
23977 item.x = item.x + ((float)chart->slots[slot].index);
23978
23979 /* user chart bar selection */
23980 if (!(layout->flags & NK_WINDOW_ROM) &&
23981 NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
23982 ret = NK_CHART_HOVERING;
23983 ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
23985 color = chart->slots[slot].highlight;
23986 }
23987 nk_fill_rect(out, item, 0, color);
23988 chart->slots[slot].index += 1;
23989 return ret;
23990}
23992nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
23993{
23994 nk_flags flags;
23995 struct nk_window *win;
23996
23997 NK_ASSERT(ctx);
23998 NK_ASSERT(ctx->current);
23999 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
24000 NK_ASSERT(slot < ctx->current->layout->chart.slot);
24001 if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
24002 if (slot >= ctx->current->layout->chart.slot) return nk_false;
24003
24004 win = ctx->current;
24005 if (win->layout->chart.slot < slot) return nk_false;
24006 switch (win->layout->chart.slots[slot].type) {
24007 case NK_CHART_LINES:
24008 flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
24009 case NK_CHART_COLUMN:
24010 flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
24011 default:
24012 case NK_CHART_MAX:
24013 flags = 0;
24014 }
24015 return flags;
24016}
24018nk_chart_push(struct nk_context *ctx, float value)
24019{
24020 return nk_chart_push_slot(ctx, value, 0);
24021}
24022NK_API void
24023nk_chart_end(struct nk_context *ctx)
24024{
24025 struct nk_window *win;
24026 struct nk_chart *chart;
24027
24028 NK_ASSERT(ctx);
24029 NK_ASSERT(ctx->current);
24030 if (!ctx || !ctx->current)
24031 return;
24032
24033 win = ctx->current;
24034 chart = &win->layout->chart;
24035 NK_MEMSET(chart, 0, sizeof(*chart));
24036 return;
24037}
24038NK_API void
24039nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
24040 int count, int offset)
24041{
24042 int i = 0;
24043 float min_value;
24044 float max_value;
24045
24046 NK_ASSERT(ctx);
24047 NK_ASSERT(values);
24048 if (!ctx || !values || !count) return;
24049
24050 min_value = values[offset];
24051 max_value = values[offset];
24052 for (i = 0; i < count; ++i) {
24053 min_value = NK_MIN(values[i + offset], min_value);
24054 max_value = NK_MAX(values[i + offset], max_value);
24055 }
24056
24057 if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
24058 for (i = 0; i < count; ++i)
24059 nk_chart_push(ctx, values[i + offset]);
24060 nk_chart_end(ctx);
24061 }
24062}
24063NK_API void
24064nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
24065 float(*value_getter)(void* user, int index), int count, int offset)
24066{
24067 int i = 0;
24068 float min_value;
24069 float max_value;
24070
24071 NK_ASSERT(ctx);
24072 NK_ASSERT(value_getter);
24073 if (!ctx || !value_getter || !count) return;
24074
24075 max_value = min_value = value_getter(userdata, offset);
24076 for (i = 0; i < count; ++i) {
24077 float value = value_getter(userdata, i + offset);
24078 min_value = NK_MIN(value, min_value);
24079 max_value = NK_MAX(value, max_value);
24080 }
24081
24082 if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
24083 for (i = 0; i < count; ++i)
24084 nk_chart_push(ctx, value_getter(userdata, i + offset));
24085 nk_chart_end(ctx);
24086 }
24087}
24088
24089
24090
24091
24092/* ==============================================================
24093 *
24094 * COLOR PICKER
24095 *
24096 * ===============================================================*/
24097NK_LIB int
24098nk_color_picker_behavior(nk_flags *state,
24099 const struct nk_rect *bounds, const struct nk_rect *matrix,
24100 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
24101 struct nk_colorf *color, const struct nk_input *in)
24102{
24103 float hsva[4];
24104 int value_changed = 0;
24105 int hsv_changed = 0;
24106
24107 NK_ASSERT(state);
24108 NK_ASSERT(matrix);
24109 NK_ASSERT(hue_bar);
24110 NK_ASSERT(color);
24111
24112 /* color matrix */
24113 nk_colorf_hsva_fv(hsva, *color);
24114 if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
24115 hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
24116 hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
24117 value_changed = hsv_changed = 1;
24118 }
24119 /* hue bar */
24120 if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
24121 hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
24122 value_changed = hsv_changed = 1;
24123 }
24124 /* alpha bar */
24125 if (alpha_bar) {
24126 if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
24127 hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
24128 value_changed = 1;
24129 }
24130 }
24131 nk_widget_state_reset(state);
24132 if (hsv_changed) {
24133 *color = nk_hsva_colorfv(hsva);
24134 *state = NK_WIDGET_STATE_ACTIVE;
24135 }
24136 if (value_changed) {
24137 color->a = hsva[3];
24138 *state = NK_WIDGET_STATE_ACTIVE;
24139 }
24140 /* set color picker widget state */
24141 if (nk_input_is_mouse_hovering_rect(in, *bounds))
24142 *state = NK_WIDGET_STATE_HOVERED;
24143 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
24144 *state |= NK_WIDGET_STATE_ENTERED;
24145 else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
24146 *state |= NK_WIDGET_STATE_LEFT;
24147 return value_changed;
24148}
24149NK_LIB void
24150nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
24151 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
24152 struct nk_colorf col)
24153{
24154 NK_STORAGE const struct nk_color black = {0,0,0,255};
24155 NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
24156 NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
24157
24158 const float crosshair_size = 7.0f;
24159 struct nk_color temp;
24160 float hsva[4];
24161 float line_y;
24162 int i;
24163
24164 NK_ASSERT(o);
24165 NK_ASSERT(matrix);
24166 NK_ASSERT(hue_bar);
24167
24168 /* draw hue bar */
24169 nk_colorf_hsva_fv(hsva, col);
24170 for (i = 0; i < 6; ++i) {
24171 NK_GLOBAL const struct nk_color hue_colors[] = {
24172 {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255},
24173 {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255}
24174 };
24176 nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
24177 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
24178 hue_colors[i+1], hue_colors[i+1]);
24179 }
24180 line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
24181 nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
24182 line_y, 1, nk_rgb(255,255,255));
24183
24184 /* draw alpha bar */
24185 if (alpha_bar) {
24186 float alpha = NK_SATURATE(col.a);
24187 line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f);
24188
24189 nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
24190 nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
24191 line_y, 1, nk_rgb(255,255,255));
24192 }
24193
24194 /* draw color matrix */
24195 temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
24196 nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
24197 nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
24198
24199 /* draw cross-hair */
24200 {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
24201 p.x = (float)(int)(matrix->x + S * matrix->w);
24202 p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
24203 nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
24204 nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
24205 nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
24206 nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
24207}
24208NK_LIB int
24209nk_do_color_picker(nk_flags *state,
24210 struct nk_command_buffer *out, struct nk_colorf *col,
24211 enum nk_color_format fmt, struct nk_rect bounds,
24212 struct nk_vec2 padding, const struct nk_input *in,
24213 const struct nk_user_font *font)
24214{
24215 int ret = 0;
24216 struct nk_rect matrix;
24217 struct nk_rect hue_bar;
24218 struct nk_rect alpha_bar;
24219 float bar_w;
24220
24221 NK_ASSERT(out);
24222 NK_ASSERT(col);
24223 NK_ASSERT(state);
24224 NK_ASSERT(font);
24225 if (!out || !col || !state || !font)
24226 return ret;
24227
24228 bar_w = font->height;
24229 bounds.x += padding.x;
24230 bounds.y += padding.x;
24231 bounds.w -= 2 * padding.x;
24232 bounds.h -= 2 * padding.y;
24233
24234 matrix.x = bounds.x;
24235 matrix.y = bounds.y;
24236 matrix.h = bounds.h;
24237 matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
24238
24239 hue_bar.w = bar_w;
24240 hue_bar.y = bounds.y;
24241 hue_bar.h = matrix.h;
24242 hue_bar.x = matrix.x + matrix.w + padding.x;
24243
24244 alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
24245 alpha_bar.y = bounds.y;
24246 alpha_bar.w = bar_w;
24247 alpha_bar.h = matrix.h;
24248
24249 ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
24250 (fmt == NK_RGBA) ? &alpha_bar:0, col, in);
24251 nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col);
24252 return ret;
24253}
24254NK_API int
24255nk_color_pick(struct nk_context * ctx, struct nk_colorf *color,
24256 enum nk_color_format fmt)
24257{
24258 struct nk_window *win;
24259 struct nk_panel *layout;
24260 const struct nk_style *config;
24261 const struct nk_input *in;
24262
24263 enum nk_widget_layout_states state;
24264 struct nk_rect bounds;
24265
24266 NK_ASSERT(ctx);
24267 NK_ASSERT(color);
24268 NK_ASSERT(ctx->current);
24269 NK_ASSERT(ctx->current->layout);
24270 if (!ctx || !ctx->current || !ctx->current->layout || !color)
24271 return 0;
24272
24273 win = ctx->current;
24274 config = &ctx->style;
24275 layout = win->layout;
24276 state = nk_widget(&bounds, ctx);
24277 if (!state) return 0;
24278 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
24279 return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
24280 nk_vec2(0,0), in, config->font);
24281}
24282NK_API struct nk_colorf
24283nk_color_picker(struct nk_context *ctx, struct nk_colorf color,
24284 enum nk_color_format fmt)
24285{
24286 nk_color_pick(ctx, &color, fmt);
24287 return color;
24288}
24289
24290
24291
24292
24293/* ==============================================================
24294 *
24295 * COMBO
24296 *
24297 * ===============================================================*/
24298NK_INTERN int
24299nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
24300 struct nk_vec2 size, int is_clicked, struct nk_rect header)
24301{
24302 struct nk_window *popup;
24303 int is_open = 0;
24304 int is_active = 0;
24305 struct nk_rect body;
24306 nk_hash hash;
24307
24308 NK_ASSERT(ctx);
24309 NK_ASSERT(ctx->current);
24310 NK_ASSERT(ctx->current->layout);
24311 if (!ctx || !ctx->current || !ctx->current->layout)
24312 return 0;
24313
24314 popup = win->popup.win;
24315 body.x = header.x;
24316 body.w = size.x;
24317 body.y = header.y + header.h-ctx->style.window.combo_border;
24318 body.h = size.y;
24319
24320 hash = win->popup.combo_count++;
24321 is_open = (popup) ? nk_true:nk_false;
24322 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
24323 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
24324 (!is_open && !is_active && !is_clicked)) return 0;
24325 if (!nk_nonblock_begin(ctx, 0, body,
24326 (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
24327
24328 win->popup.type = NK_PANEL_COMBO;
24329 win->popup.name = hash;
24330 return 1;
24331}
24332NK_API int
24333nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
24334 struct nk_vec2 size)
24335{
24336 const struct nk_input *in;
24337 struct nk_window *win;
24338 struct nk_style *style;
24339
24341 int is_clicked = nk_false;
24342 struct nk_rect header;
24343 const struct nk_style_item *background;
24344 struct nk_text text;
24345
24346 NK_ASSERT(ctx);
24347 NK_ASSERT(selected);
24348 NK_ASSERT(ctx->current);
24349 NK_ASSERT(ctx->current->layout);
24350 if (!ctx || !ctx->current || !ctx->current->layout || !selected)
24351 return 0;
24352
24353 win = ctx->current;
24354 style = &ctx->style;
24355 s = nk_widget(&header, ctx);
24356 if (s == NK_WIDGET_INVALID)
24357 return 0;
24358
24359 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24361 is_clicked = nk_true;
24362
24363 /* draw combo box header background and border */
24365 background = &style->combo.active;
24366 text.text = style->combo.label_active;
24367 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24368 background = &style->combo.hover;
24369 text.text = style->combo.label_hover;
24370 } else {
24371 background = &style->combo.normal;
24372 text.text = style->combo.label_normal;
24373 }
24374 if (background->type == NK_STYLE_ITEM_IMAGE) {
24375 text.background = nk_rgba(0,0,0,0);
24376 nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24377 } else {
24378 text.background = background->data.color;
24379 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24380 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24381 }
24382 {
24383 /* print currently selected text item */
24384 struct nk_rect label;
24385 struct nk_rect button;
24386 struct nk_rect content;
24387
24388 enum nk_symbol_type sym;
24390 sym = style->combo.sym_hover;
24391 else if (is_clicked)
24392 sym = style->combo.sym_active;
24393 else sym = style->combo.sym_normal;
24394
24395 /* calculate button */
24396 button.w = header.h - 2 * style->combo.button_padding.y;
24397 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24398 button.y = header.y + style->combo.button_padding.y;
24399 button.h = button.w;
24400
24401 content.x = button.x + style->combo.button.padding.x;
24402 content.y = button.y + style->combo.button.padding.y;
24403 content.w = button.w - 2 * style->combo.button.padding.x;
24404 content.h = button.h - 2 * style->combo.button.padding.y;
24405
24406 /* draw selected label */
24407 text.padding = nk_vec2(0,0);
24408 label.x = header.x + style->combo.content_padding.x;
24409 label.y = header.y + style->combo.content_padding.y;
24410 label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
24411 label.h = header.h - 2 * style->combo.content_padding.y;
24412 nk_widget_text(&win->buffer, label, selected, len, &text,
24413 NK_TEXT_LEFT, ctx->style.font);
24414
24415 /* draw open/close button */
24416 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24417 &ctx->style.combo.button, sym, style->font);
24418 }
24419 return nk_combo_begin(ctx, win, size, is_clicked, header);
24420}
24421NK_API int
24422nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
24423{
24424 return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);
24425}
24426NK_API int
24427nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
24428{
24429 struct nk_window *win;
24430 struct nk_style *style;
24431 const struct nk_input *in;
24432
24433 struct nk_rect header;
24434 int is_clicked = nk_false;
24436 const struct nk_style_item *background;
24437
24438 NK_ASSERT(ctx);
24439 NK_ASSERT(ctx->current);
24440 NK_ASSERT(ctx->current->layout);
24441 if (!ctx || !ctx->current || !ctx->current->layout)
24442 return 0;
24443
24444 win = ctx->current;
24445 style = &ctx->style;
24446 s = nk_widget(&header, ctx);
24447 if (s == NK_WIDGET_INVALID)
24448 return 0;
24449
24450 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24452 is_clicked = nk_true;
24453
24454 /* draw combo box header background and border */
24456 background = &style->combo.active;
24458 background = &style->combo.hover;
24459 else background = &style->combo.normal;
24460
24461 if (background->type == NK_STYLE_ITEM_IMAGE) {
24462 nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
24463 } else {
24464 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24465 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24466 }
24467 {
24468 struct nk_rect content;
24469 struct nk_rect button;
24470 struct nk_rect bounds;
24471
24472 enum nk_symbol_type sym;
24474 sym = style->combo.sym_hover;
24475 else if (is_clicked)
24476 sym = style->combo.sym_active;
24477 else sym = style->combo.sym_normal;
24478
24479 /* calculate button */
24480 button.w = header.h - 2 * style->combo.button_padding.y;
24481 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24482 button.y = header.y + style->combo.button_padding.y;
24483 button.h = button.w;
24484
24485 content.x = button.x + style->combo.button.padding.x;
24486 content.y = button.y + style->combo.button.padding.y;
24487 content.w = button.w - 2 * style->combo.button.padding.x;
24488 content.h = button.h - 2 * style->combo.button.padding.y;
24489
24490 /* draw color */
24491 bounds.h = header.h - 4 * style->combo.content_padding.y;
24492 bounds.y = header.y + 2 * style->combo.content_padding.y;
24493 bounds.x = header.x + 2 * style->combo.content_padding.x;
24494 bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
24495 nk_fill_rect(&win->buffer, bounds, 0, color);
24496
24497 /* draw open/close button */
24498 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24499 &ctx->style.combo.button, sym, style->font);
24500 }
24501 return nk_combo_begin(ctx, win, size, is_clicked, header);
24502}
24503NK_API int
24504nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
24505{
24506 struct nk_window *win;
24507 struct nk_style *style;
24508 const struct nk_input *in;
24509
24510 struct nk_rect header;
24511 int is_clicked = nk_false;
24513 const struct nk_style_item *background;
24514 struct nk_color sym_background;
24515 struct nk_color symbol_color;
24516
24517 NK_ASSERT(ctx);
24518 NK_ASSERT(ctx->current);
24519 NK_ASSERT(ctx->current->layout);
24520 if (!ctx || !ctx->current || !ctx->current->layout)
24521 return 0;
24522
24523 win = ctx->current;
24524 style = &ctx->style;
24525 s = nk_widget(&header, ctx);
24526 if (s == NK_WIDGET_INVALID)
24527 return 0;
24528
24529 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24531 is_clicked = nk_true;
24532
24533 /* draw combo box header background and border */
24535 background = &style->combo.active;
24536 symbol_color = style->combo.symbol_active;
24537 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24538 background = &style->combo.hover;
24539 symbol_color = style->combo.symbol_hover;
24540 } else {
24541 background = &style->combo.normal;
24542 symbol_color = style->combo.symbol_hover;
24543 }
24544
24545 if (background->type == NK_STYLE_ITEM_IMAGE) {
24546 sym_background = nk_rgba(0,0,0,0);
24547 nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24548 } else {
24549 sym_background = background->data.color;
24550 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24551 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24552 }
24553 {
24554 struct nk_rect bounds = {0,0,0,0};
24555 struct nk_rect content;
24556 struct nk_rect button;
24557
24558 enum nk_symbol_type sym;
24560 sym = style->combo.sym_hover;
24561 else if (is_clicked)
24562 sym = style->combo.sym_active;
24563 else sym = style->combo.sym_normal;
24564
24565 /* calculate button */
24566 button.w = header.h - 2 * style->combo.button_padding.y;
24567 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
24568 button.y = header.y + style->combo.button_padding.y;
24569 button.h = button.w;
24570
24571 content.x = button.x + style->combo.button.padding.x;
24572 content.y = button.y + style->combo.button.padding.y;
24573 content.w = button.w - 2 * style->combo.button.padding.x;
24574 content.h = button.h - 2 * style->combo.button.padding.y;
24575
24576 /* draw symbol */
24577 bounds.h = header.h - 2 * style->combo.content_padding.y;
24578 bounds.y = header.y + style->combo.content_padding.y;
24579 bounds.x = header.x + style->combo.content_padding.x;
24580 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
24581 nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
24582 1.0f, style->font);
24583
24584 /* draw open/close button */
24585 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
24586 &ctx->style.combo.button, sym, style->font);
24587 }
24588 return nk_combo_begin(ctx, win, size, is_clicked, header);
24589}
24590NK_API int
24591nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
24592 enum nk_symbol_type symbol, struct nk_vec2 size)
24593{
24594 struct nk_window *win;
24595 struct nk_style *style;
24596 struct nk_input *in;
24597
24598 struct nk_rect header;
24599 int is_clicked = nk_false;
24601 const struct nk_style_item *background;
24602 struct nk_color symbol_color;
24603 struct nk_text text;
24604
24605 NK_ASSERT(ctx);
24606 NK_ASSERT(ctx->current);
24607 NK_ASSERT(ctx->current->layout);
24608 if (!ctx || !ctx->current || !ctx->current->layout)
24609 return 0;
24610
24611 win = ctx->current;
24612 style = &ctx->style;
24613 s = nk_widget(&header, ctx);
24614 if (!s) return 0;
24615
24616 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24618 is_clicked = nk_true;
24619
24620 /* draw combo box header background and border */
24622 background = &style->combo.active;
24623 symbol_color = style->combo.symbol_active;
24624 text.text = style->combo.label_active;
24625 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24626 background = &style->combo.hover;
24627 symbol_color = style->combo.symbol_hover;
24628 text.text = style->combo.label_hover;
24629 } else {
24630 background = &style->combo.normal;
24631 symbol_color = style->combo.symbol_normal;
24632 text.text = style->combo.label_normal;
24633 }
24634 if (background->type == NK_STYLE_ITEM_IMAGE) {
24635 text.background = nk_rgba(0,0,0,0);
24636 nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24637 } else {
24638 text.background = background->data.color;
24639 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24640 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24641 }
24642 {
24643 struct nk_rect content;
24644 struct nk_rect button;
24645 struct nk_rect label;
24646 struct nk_rect image;
24647
24648 enum nk_symbol_type sym;
24650 sym = style->combo.sym_hover;
24651 else if (is_clicked)
24652 sym = style->combo.sym_active;
24653 else sym = style->combo.sym_normal;
24654
24655 /* calculate button */
24656 button.w = header.h - 2 * style->combo.button_padding.y;
24657 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24658 button.y = header.y + style->combo.button_padding.y;
24659 button.h = button.w;
24660
24661 content.x = button.x + style->combo.button.padding.x;
24662 content.y = button.y + style->combo.button.padding.y;
24663 content.w = button.w - 2 * style->combo.button.padding.x;
24664 content.h = button.h - 2 * style->combo.button.padding.y;
24665 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24666 &ctx->style.combo.button, sym, style->font);
24667
24668 /* draw symbol */
24669 image.x = header.x + style->combo.content_padding.x;
24670 image.y = header.y + style->combo.content_padding.y;
24671 image.h = header.h - 2 * style->combo.content_padding.y;
24672 image.w = image.h;
24673 nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
24674 1.0f, style->font);
24675
24676 /* draw label */
24677 text.padding = nk_vec2(0,0);
24678 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
24679 label.y = header.y + style->combo.content_padding.y;
24680 label.w = (button.x - style->combo.content_padding.x) - label.x;
24681 label.h = header.h - 2 * style->combo.content_padding.y;
24682 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
24683 }
24684 return nk_combo_begin(ctx, win, size, is_clicked, header);
24685}
24686NK_API int
24687nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
24688{
24689 struct nk_window *win;
24690 struct nk_style *style;
24691 const struct nk_input *in;
24692
24693 struct nk_rect header;
24694 int is_clicked = nk_false;
24696 const struct nk_style_item *background;
24697
24698 NK_ASSERT(ctx);
24699 NK_ASSERT(ctx->current);
24700 NK_ASSERT(ctx->current->layout);
24701 if (!ctx || !ctx->current || !ctx->current->layout)
24702 return 0;
24703
24704 win = ctx->current;
24705 style = &ctx->style;
24706 s = nk_widget(&header, ctx);
24707 if (s == NK_WIDGET_INVALID)
24708 return 0;
24709
24710 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24712 is_clicked = nk_true;
24713
24714 /* draw combo box header background and border */
24716 background = &style->combo.active;
24718 background = &style->combo.hover;
24719 else background = &style->combo.normal;
24720
24721 if (background->type == NK_STYLE_ITEM_IMAGE) {
24722 nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24723 } else {
24724 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24725 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24726 }
24727 {
24728 struct nk_rect bounds = {0,0,0,0};
24729 struct nk_rect content;
24730 struct nk_rect button;
24731
24732 enum nk_symbol_type sym;
24734 sym = style->combo.sym_hover;
24735 else if (is_clicked)
24736 sym = style->combo.sym_active;
24737 else sym = style->combo.sym_normal;
24738
24739 /* calculate button */
24740 button.w = header.h - 2 * style->combo.button_padding.y;
24741 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
24742 button.y = header.y + style->combo.button_padding.y;
24743 button.h = button.w;
24744
24745 content.x = button.x + style->combo.button.padding.x;
24746 content.y = button.y + style->combo.button.padding.y;
24747 content.w = button.w - 2 * style->combo.button.padding.x;
24748 content.h = button.h - 2 * style->combo.button.padding.y;
24749
24750 /* draw image */
24751 bounds.h = header.h - 2 * style->combo.content_padding.y;
24752 bounds.y = header.y + style->combo.content_padding.y;
24753 bounds.x = header.x + style->combo.content_padding.x;
24754 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
24755 nk_draw_image(&win->buffer, bounds, &img, nk_white);
24756
24757 /* draw open/close button */
24758 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
24759 &ctx->style.combo.button, sym, style->font);
24760 }
24761 return nk_combo_begin(ctx, win, size, is_clicked, header);
24762}
24763NK_API int
24764nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
24765 struct nk_image img, struct nk_vec2 size)
24766{
24767 struct nk_window *win;
24768 struct nk_style *style;
24769 struct nk_input *in;
24770
24771 struct nk_rect header;
24772 int is_clicked = nk_false;
24774 const struct nk_style_item *background;
24775 struct nk_text text;
24776
24777 NK_ASSERT(ctx);
24778 NK_ASSERT(ctx->current);
24779 NK_ASSERT(ctx->current->layout);
24780 if (!ctx || !ctx->current || !ctx->current->layout)
24781 return 0;
24782
24783 win = ctx->current;
24784 style = &ctx->style;
24785 s = nk_widget(&header, ctx);
24786 if (!s) return 0;
24787
24788 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24790 is_clicked = nk_true;
24791
24792 /* draw combo box header background and border */
24794 background = &style->combo.active;
24795 text.text = style->combo.label_active;
24796 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24797 background = &style->combo.hover;
24798 text.text = style->combo.label_hover;
24799 } else {
24800 background = &style->combo.normal;
24801 text.text = style->combo.label_normal;
24802 }
24803 if (background->type == NK_STYLE_ITEM_IMAGE) {
24804 text.background = nk_rgba(0,0,0,0);
24805 nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24806 } else {
24807 text.background = background->data.color;
24808 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24809 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24810 }
24811 {
24812 struct nk_rect content;
24813 struct nk_rect button;
24814 struct nk_rect label;
24815 struct nk_rect image;
24816
24817 enum nk_symbol_type sym;
24819 sym = style->combo.sym_hover;
24820 else if (is_clicked)
24821 sym = style->combo.sym_active;
24822 else sym = style->combo.sym_normal;
24823
24824 /* calculate button */
24825 button.w = header.h - 2 * style->combo.button_padding.y;
24826 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24827 button.y = header.y + style->combo.button_padding.y;
24828 button.h = button.w;
24829
24830 content.x = button.x + style->combo.button.padding.x;
24831 content.y = button.y + style->combo.button.padding.y;
24832 content.w = button.w - 2 * style->combo.button.padding.x;
24833 content.h = button.h - 2 * style->combo.button.padding.y;
24834 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24835 &ctx->style.combo.button, sym, style->font);
24836
24837 /* draw image */
24838 image.x = header.x + style->combo.content_padding.x;
24839 image.y = header.y + style->combo.content_padding.y;
24840 image.h = header.h - 2 * style->combo.content_padding.y;
24841 image.w = image.h;
24842 nk_draw_image(&win->buffer, image, &img, nk_white);
24843
24844 /* draw label */
24845 text.padding = nk_vec2(0,0);
24846 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
24847 label.y = header.y + style->combo.content_padding.y;
24848 label.w = (button.x - style->combo.content_padding.x) - label.x;
24849 label.h = header.h - 2 * style->combo.content_padding.y;
24850 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
24851 }
24852 return nk_combo_begin(ctx, win, size, is_clicked, header);
24853}
24854NK_API int
24856 const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
24857{
24858 return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);
24859}
24860NK_API int
24862 const char *selected, struct nk_image img, struct nk_vec2 size)
24863{
24864 return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);
24865}
24866NK_API int
24867nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
24868{
24869 return nk_contextual_item_text(ctx, text, len, align);
24870}
24871NK_API int
24872nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
24873{
24874 return nk_contextual_item_label(ctx, label, align);
24875}
24876NK_API int
24877nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
24878 int len, nk_flags alignment)
24879{
24880 return nk_contextual_item_image_text(ctx, img, text, len, alignment);
24881}
24882NK_API int
24883nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
24884 const char *text, nk_flags alignment)
24885{
24886 return nk_contextual_item_image_label(ctx, img, text, alignment);
24887}
24888NK_API int
24890 const char *text, int len, nk_flags alignment)
24891{
24892 return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);
24893}
24894NK_API int
24896 const char *label, nk_flags alignment)
24897{
24898 return nk_contextual_item_symbol_label(ctx, sym, label, alignment);
24899}
24900NK_API void nk_combo_end(struct nk_context *ctx)
24901{
24902 nk_contextual_end(ctx);
24903}
24904NK_API void nk_combo_close(struct nk_context *ctx)
24905{
24907}
24908NK_API int
24909nk_combo(struct nk_context *ctx, const char **items, int count,
24910 int selected, int item_height, struct nk_vec2 size)
24911{
24912 int i = 0;
24913 int max_height;
24914 struct nk_vec2 item_spacing;
24915 struct nk_vec2 window_padding;
24916
24917 NK_ASSERT(ctx);
24918 NK_ASSERT(items);
24919 NK_ASSERT(ctx->current);
24920 if (!ctx || !items ||!count)
24921 return selected;
24922
24923 item_spacing = ctx->style.window.spacing;
24924 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
24925 max_height = count * item_height + count * (int)item_spacing.y;
24926 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
24927 size.y = NK_MIN(size.y, (float)max_height);
24928 if (nk_combo_begin_label(ctx, items[selected], size)) {
24929 nk_layout_row_dynamic(ctx, (float)item_height, 1);
24930 for (i = 0; i < count; ++i) {
24931 if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
24932 selected = i;
24933 }
24934 nk_combo_end(ctx);
24935 }
24936 return selected;
24937}
24938NK_API int
24939nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
24940 int separator, int selected, int count, int item_height, struct nk_vec2 size)
24941{
24942 int i;
24943 int max_height;
24944 struct nk_vec2 item_spacing;
24945 struct nk_vec2 window_padding;
24946 const char *current_item;
24947 const char *iter;
24948 int length = 0;
24949
24950 NK_ASSERT(ctx);
24951 NK_ASSERT(items_separated_by_separator);
24952 if (!ctx || !items_separated_by_separator)
24953 return selected;
24954
24955 /* calculate popup window */
24956 item_spacing = ctx->style.window.spacing;
24957 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
24958 max_height = count * item_height + count * (int)item_spacing.y;
24959 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
24960 size.y = NK_MIN(size.y, (float)max_height);
24961
24962 /* find selected item */
24963 current_item = items_separated_by_separator;
24964 for (i = 0; i < count; ++i) {
24965 iter = current_item;
24966 while (*iter && *iter != separator) iter++;
24967 length = (int)(iter - current_item);
24968 if (i == selected) break;
24969 current_item = iter + 1;
24970 }
24971
24972 if (nk_combo_begin_text(ctx, current_item, length, size)) {
24973 current_item = items_separated_by_separator;
24974 nk_layout_row_dynamic(ctx, (float)item_height, 1);
24975 for (i = 0; i < count; ++i) {
24976 iter = current_item;
24977 while (*iter && *iter != separator) iter++;
24978 length = (int)(iter - current_item);
24979 if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
24980 selected = i;
24981 current_item = current_item + length + 1;
24982 }
24983 nk_combo_end(ctx);
24984 }
24985 return selected;
24986}
24987NK_API int
24988nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
24989 int selected, int count, int item_height, struct nk_vec2 size)
24990{
24991 return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);
24992}
24993NK_API int
24994nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
24995 void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
24996{
24997 int i;
24998 int max_height;
24999 struct nk_vec2 item_spacing;
25000 struct nk_vec2 window_padding;
25001 const char *item;
25002
25003 NK_ASSERT(ctx);
25004 NK_ASSERT(item_getter);
25005 if (!ctx || !item_getter)
25006 return selected;
25007
25008 /* calculate popup window */
25009 item_spacing = ctx->style.window.spacing;
25010 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
25011 max_height = count * item_height + count * (int)item_spacing.y;
25012 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
25013 size.y = NK_MIN(size.y, (float)max_height);
25014
25015 item_getter(userdata, selected, &item);
25016 if (nk_combo_begin_label(ctx, item, size)) {
25017 nk_layout_row_dynamic(ctx, (float)item_height, 1);
25018 for (i = 0; i < count; ++i) {
25019 item_getter(userdata, i, &item);
25020 if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
25021 selected = i;
25022 }
25023 nk_combo_end(ctx);
25024 } return selected;
25025}
25026NK_API void
25027nk_combobox(struct nk_context *ctx, const char **items, int count,
25028 int *selected, int item_height, struct nk_vec2 size)
25029{
25030 *selected = nk_combo(ctx, items, count, *selected, item_height, size);
25031}
25032NK_API void
25033nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
25034 int *selected, int count, int item_height, struct nk_vec2 size)
25035{
25036 *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);
25037}
25038NK_API void
25039nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
25040 int separator,int *selected, int count, int item_height, struct nk_vec2 size)
25041{
25042 *selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
25043 *selected, count, item_height, size);
25044}
25045NK_API void
25047 void(*item_getter)(void* data, int id, const char **out_text),
25048 void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
25049{
25050 *selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size);
25051}
25052
25053
25054
25055
25056/* ===============================================================
25057 *
25058 * TOOLTIP
25059 *
25060 * ===============================================================*/
25061NK_API int
25062nk_tooltip_begin(struct nk_context *ctx, float width)
25063{
25064 int x,y,w,h;
25065 struct nk_window *win;
25066 const struct nk_input *in;
25067 struct nk_rect bounds;
25068 int ret;
25069
25070 NK_ASSERT(ctx);
25071 NK_ASSERT(ctx->current);
25072 NK_ASSERT(ctx->current->layout);
25073 if (!ctx || !ctx->current || !ctx->current->layout)
25074 return 0;
25075
25076 /* make sure that no nonblocking popup is currently active */
25077 win = ctx->current;
25078 in = &ctx->input;
25079 if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
25080 return 0;
25081
25082 w = nk_iceilf(width);
25083 h = nk_iceilf(nk_null_rect.h);
25084 x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x;
25085 y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y;
25086
25087 bounds.x = (float)x;
25088 bounds.y = (float)y;
25089 bounds.w = (float)w;
25090 bounds.h = (float)h;
25091
25093 "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
25094 if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
25097 return ret;
25098}
25099
25100NK_API void
25101nk_tooltip_end(struct nk_context *ctx)
25102{
25103 NK_ASSERT(ctx);
25104 NK_ASSERT(ctx->current);
25105 if (!ctx || !ctx->current) return;
25106 ctx->current->seq--;
25107 nk_popup_close(ctx);
25108 nk_popup_end(ctx);
25109}
25110NK_API void
25111nk_tooltip(struct nk_context *ctx, const char *text)
25112{
25113 const struct nk_style *style;
25114 struct nk_vec2 padding;
25115
25116 int text_len;
25117 float text_width;
25118 float text_height;
25119
25120 NK_ASSERT(ctx);
25121 NK_ASSERT(ctx->current);
25122 NK_ASSERT(ctx->current->layout);
25123 NK_ASSERT(text);
25124 if (!ctx || !ctx->current || !ctx->current->layout || !text)
25125 return;
25126
25127 /* fetch configuration data */
25128 style = &ctx->style;
25129 padding = style->window.padding;
25130
25131 /* calculate size of the text and tooltip */
25132 text_len = nk_strlen(text);
25133 text_width = style->font->width(style->font->userdata,
25134 style->font->height, text, text_len);
25135 text_width += (4 * padding.x);
25136 text_height = (style->font->height + 2 * padding.y);
25137
25138 /* execute tooltip and fill with text */
25139 if (nk_tooltip_begin(ctx, (float)text_width)) {
25140 nk_layout_row_dynamic(ctx, (float)text_height, 1);
25141 nk_text(ctx, text, text_len, NK_TEXT_LEFT);
25142 nk_tooltip_end(ctx);
25143 }
25144}
25145#ifdef NK_INCLUDE_STANDARD_VARARGS
25146NK_API void
25147nk_tooltipf(struct nk_context *ctx, const char *fmt, ...)
25148{
25149 va_list args;
25150 va_start(args, fmt);
25151 nk_tooltipfv(ctx, fmt, args);
25152 va_end(args);
25153}
25154NK_API void
25155nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
25156{
25157 char buf[256];
25158 nk_strfmt(buf, NK_LEN(buf), fmt, args);
25159 nk_tooltip(ctx, buf);
25160}
25161#endif
25162
25163
25164#endif /* NK_IMPLEMENTATION */
25165
25166/*
25209
25521*/
25522
NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color)
NK_API struct nk_rect nk_window_get_content_region(struct nk_context *)
NK_API struct nk_window * nk_window_find(struct nk_context *ctx, const char *name)
void(* nk_plugin_copy)(nk_handle, const char *, int len)
Definition: nuklear.h:269
#define NK_VECTOR_STACK_SIZE
Definition: nuklear.h:5260
NK_API const char * nk_str_at_const(const struct nk_str *, int pos, nk_rune *unicode, int *len)
NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a)
NK_API void nk_str_free(struct nk_str *)
NK_API char * nk_str_at_char(struct nk_str *, int pos)
NK_API int nk_combo_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API void nk_tree_pop(struct nk_context *)
NK_API struct nk_color nk_hsva_iv(const int *hsva)
NK_API struct nk_rect nk_layout_space_bounds(struct nk_context *)
NK_API struct nk_color nk_rgb(int r, int g, int b)
NK_API void nk_free(struct nk_context *)
@ nk_true
Definition: nuklear.h:239
@ nk_false
Definition: nuklear.h:239
NK_API void nk_str_delete_runes(struct nk_str *, int pos, int len)
NK_API void nk_stroke_rect(struct nk_command_buffer *, struct nk_rect, float rounding, float line_thickness, struct nk_color)
NK_API void nk_property_int(struct nk_context *, const char *name, int min, int *val, int max, int step, float inc_per_pixel)
NK_INT8 nk_char
Definition: nuklear.h:181
NK_API nk_size nk_buffer_total(struct nk_buffer *)
NK_API float nk_widget_width(struct nk_context *)
#define NK_API
Definition: nuklear.h:45
NK_API int nk_group_scrolled_offset_begin(struct nk_context *, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
#define NK_FLAG(x)
Definition: nuklear.h:60
NK_API void nk_buffer_mark(struct nk_buffer *, enum nk_buffer_allocation_type type)
NK_API nk_handle nk_handle_ptr(void *)
NK_API void nk_combobox_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int *selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_contextual_item_text(struct nk_context *, const char *, int, nk_flags align)
NK_API int nk_combo_begin_image_label(struct nk_context *, const char *selected, struct nk_image, struct nk_vec2 size)
NK_API nk_uint nk_color_u32(struct nk_color)
NK_API struct nk_image nk_image_handle(nk_handle)
NK_API void nk_menu_close(struct nk_context *)
NK_API int nk_item_is_any_active(struct nk_context *)
NK_API void nk_color_dv(double *rgba_out, struct nk_color)
NK_API int nk_selectable_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags align, int *value)
NK_API void nk_image(struct nk_context *, struct nk_image)
#define NK_CONTAINER_OF(ptr, type, member)
Definition: nuklear.h:5445
NK_API struct nk_rect nk_get_null_rect(void)
NK_API int nk_slide_int(struct nk_context *, int min, int val, int max, int step)
NK_API struct nk_color nk_hsv_iv(const int *hsv)
NK_API int nk_input_is_key_pressed(const struct nk_input *, enum nk_keys)
#define NK_STORAGE
Definition: nuklear.h:57
NK_API void nk_layout_row_end(struct nk_context *)
NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context *)
NK_API void nk_input_end(struct nk_context *)
NK_API void nk_menu_end(struct nk_context *)
NK_API int nk_check_label(struct nk_context *, const char *, int active)
nk_keys
Definition: nuklear.h:518
@ NK_KEY_LEFT
Definition: nuklear.h:531
@ NK_KEY_TEXT_SELECT_ALL
Definition: nuklear.h:543
@ NK_KEY_TEXT_WORD_LEFT
Definition: nuklear.h:544
@ NK_KEY_TEXT_REPLACE_MODE
Definition: nuklear.h:535
@ NK_KEY_TEXT_REDO
Definition: nuklear.h:542
@ NK_KEY_UP
Definition: nuklear.h:529
@ NK_KEY_TEXT_END
Definition: nuklear.h:540
@ NK_KEY_TEXT_UNDO
Definition: nuklear.h:541
@ NK_KEY_TEXT_RESET_MODE
Definition: nuklear.h:536
@ NK_KEY_DEL
Definition: nuklear.h:522
@ NK_KEY_NONE
Definition: nuklear.h:519
@ NK_KEY_SCROLL_END
Definition: nuklear.h:548
@ NK_KEY_CTRL
Definition: nuklear.h:521
@ NK_KEY_MAX
Definition: nuklear.h:551
@ NK_KEY_TEXT_LINE_START
Definition: nuklear.h:537
@ NK_KEY_TEXT_INSERT_MODE
Definition: nuklear.h:534
@ NK_KEY_COPY
Definition: nuklear.h:526
@ NK_KEY_SCROLL_UP
Definition: nuklear.h:550
@ NK_KEY_RIGHT
Definition: nuklear.h:532
@ NK_KEY_TAB
Definition: nuklear.h:524
@ NK_KEY_PASTE
Definition: nuklear.h:528
@ NK_KEY_SHIFT
Definition: nuklear.h:520
@ NK_KEY_TEXT_LINE_END
Definition: nuklear.h:538
@ NK_KEY_ENTER
Definition: nuklear.h:523
@ NK_KEY_TEXT_WORD_RIGHT
Definition: nuklear.h:545
@ NK_KEY_BACKSPACE
Definition: nuklear.h:525
@ NK_KEY_SCROLL_DOWN
Definition: nuklear.h:549
@ NK_KEY_DOWN
Definition: nuklear.h:530
@ NK_KEY_CUT
Definition: nuklear.h:527
@ NK_KEY_SCROLL_START
Definition: nuklear.h:547
@ NK_KEY_TEXT_START
Definition: nuklear.h:539
#define nk_vec2_add(a, b)
Definition: nuklear.h:5413
NK_API int nk_button_text_styled(struct nk_context *, const struct nk_style_button *, const char *title, int len)
NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name)
NK_API void nk_window_close(struct nk_context *ctx, const char *name)
nk_edit_flags
Definition: nuklear.h:3198
@ NK_EDIT_MULTILINE
Definition: nuklear.h:3210
@ NK_EDIT_NO_HORIZONTAL_SCROLL
Definition: nuklear.h:3208
@ NK_EDIT_ALWAYS_INSERT_MODE
Definition: nuklear.h:3209
@ NK_EDIT_SIG_ENTER
Definition: nuklear.h:3202
@ NK_EDIT_READ_ONLY
Definition: nuklear.h:3200
@ NK_EDIT_AUTO_SELECT
Definition: nuklear.h:3201
@ NK_EDIT_CLIPBOARD
Definition: nuklear.h:3206
@ NK_EDIT_SELECTABLE
Definition: nuklear.h:3205
@ NK_EDIT_NO_CURSOR
Definition: nuklear.h:3204
@ NK_EDIT_ALLOW_TAB
Definition: nuklear.h:3203
@ NK_EDIT_DEFAULT
Definition: nuklear.h:3199
@ NK_EDIT_GOTO_END_ON_ACTIVATE
Definition: nuklear.h:3211
@ NK_EDIT_CTRL_ENTER_NEWLINE
Definition: nuklear.h:3207
NK_API int nk_tree_image_push_hashed(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
NK_API int nk_slider_int(struct nk_context *, int min, int *val, int max, int step)
NK_API struct nk_vec2 nk_vec2iv(const int *xy)
NK_API struct nk_color nk_rgba_hex(const char *rgb)
NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color)
NK_API void nk_input_key(struct nk_context *, enum nk_keys, int down)
NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color)
nk_uint nk_flags
Definition: nuklear.h:192
#define NK_ALIGNOF(t)
Definition: nuklear.h:5462
NK_UINT8 nk_byte
Definition: nuklear.h:183
NK_API void nk_popup_set_scroll(struct nk_context *, nk_uint offset_x, nk_uint offset_y)
nk_convert_result
Definition: nuklear.h:926
@ NK_CONVERT_COMMAND_BUFFER_FULL
Definition: nuklear.h:929
@ NK_CONVERT_VERTEX_BUFFER_FULL
Definition: nuklear.h:930
@ NK_CONVERT_SUCCESS
Definition: nuklear.h:927
@ NK_CONVERT_INVALID_PARAM
Definition: nuklear.h:928
@ NK_CONVERT_ELEMENT_BUFFER_FULL
Definition: nuklear.h:931
NK_API float nk_window_get_width(const struct nk_context *)
NK_API int nk_button_image_label(struct nk_context *, struct nk_image img, const char *, nk_flags text_alignment)
nk_panel_row_layout_type
Definition: nuklear.h:5067
@ NK_LAYOUT_DYNAMIC
Definition: nuklear.h:5071
@ NK_LAYOUT_COUNT
Definition: nuklear.h:5077
@ NK_LAYOUT_DYNAMIC_ROW
Definition: nuklear.h:5069
@ NK_LAYOUT_STATIC_ROW
Definition: nuklear.h:5073
@ NK_LAYOUT_STATIC
Definition: nuklear.h:5075
@ NK_LAYOUT_STATIC_FREE
Definition: nuklear.h:5074
@ NK_LAYOUT_DYNAMIC_FIXED
Definition: nuklear.h:5068
@ NK_LAYOUT_TEMPLATE
Definition: nuklear.h:5076
@ NK_LAYOUT_DYNAMIC_FREE
Definition: nuklear.h:5070
@ NK_LAYOUT_STATIC_FIXED
Definition: nuklear.h:5072
NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region)
NK_API void nk_contextual_close(struct nk_context *)
NK_API int nk_utf_len(const char *, int byte_len)
NK_API struct nk_color nk_hsv(int h, int s, int v)
NK_API void nk_plot_function(struct nk_context *, enum nk_chart_type, void *userdata, float(*value_getter)(void *user, int index), int count, int offset)
NK_API int nk_style_pop_style_item(struct nk_context *)
NK_API void nk_input_begin(struct nk_context *)
NK_API struct nk_style_item nk_style_item_image(struct nk_image img)
NK_API int nk_select_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags align, int value)
NK_API int nk_tooltip_begin(struct nk_context *, float width)
NK_API unsigned nk_check_flags_text(struct nk_context *, const char *, int, unsigned int flags, unsigned int value)
NK_API int nk_select_label(struct nk_context *, const char *, nk_flags align, int value)
NK_API struct nk_vec2 nk_rect_pos(struct nk_rect)
NK_API float nk_propertyf(struct nk_context *, const char *name, float min, float val, float max, float step, float inc_per_pixel)
NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context *, nk_flags, char *buffer, int max, nk_plugin_filter)
NK_API int nk_combo_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size)
nk_uint nk_hash
Definition: nuklear.h:191
#define NK_UINT8
Definition: nuklear.h:127
NK_API int nk_input_is_mouse_pressed(const struct nk_input *, enum nk_buttons)
NK_API int nk_filter_default(const struct nk_text_edit *, nk_rune unicode)
NK_API void nk_layout_space_end(struct nk_context *)
NK_API int nk_input_is_mouse_released(const struct nk_input *, enum nk_buttons)
NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv)
NK_API int nk_checkbox_flags_label(struct nk_context *, const char *, unsigned int *flags, unsigned int value)
NK_API void nk_window_set_bounds(struct nk_context *, const char *name, struct nk_rect bounds)
NK_API int nk_style_set_cursor(struct nk_context *, enum nk_style_cursor)
NK_API struct nk_color nk_rgb_fv(const float *rgb)
NK_API void nk_popup_end(struct nk_context *)
NK_API int nk_select_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int value)
nk_chart_type
Definition: nuklear.h:258
@ NK_CHART_COLUMN
Definition: nuklear.h:258
@ NK_CHART_LINES
Definition: nuklear.h:258
@ NK_CHART_MAX
Definition: nuklear.h:258
nk_chart_event
Definition: nuklear.h:259
@ NK_CHART_HOVERING
Definition: nuklear.h:259
@ NK_CHART_CLICKED
Definition: nuklear.h:259
NK_API struct nk_color nk_rgb_hex(const char *rgb)
NK_API int nk_textedit_cut(struct nk_text_edit *)
NK_API void nk_edit_focus(struct nk_context *, nk_flags flags)
NK_API int nk_str_insert_at_char(struct nk_str *, int pos, const char *, int)
NK_API int nk_button_text(struct nk_context *, const char *title, int len)
NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context *, struct nk_vec2)
nk_symbol_type
Definition: nuklear.h:276
@ NK_SYMBOL_MAX
Definition: nuklear.h:290
@ NK_SYMBOL_X
Definition: nuklear.h:278
@ NK_SYMBOL_TRIANGLE_UP
Definition: nuklear.h:284
@ NK_SYMBOL_NONE
Definition: nuklear.h:277
@ NK_SYMBOL_TRIANGLE_LEFT
Definition: nuklear.h:286
@ NK_SYMBOL_CIRCLE_SOLID
Definition: nuklear.h:280
@ NK_SYMBOL_UNDERSCORE
Definition: nuklear.h:279
@ NK_SYMBOL_CIRCLE_OUTLINE
Definition: nuklear.h:281
@ NK_SYMBOL_TRIANGLE_DOWN
Definition: nuklear.h:285
@ NK_SYMBOL_RECT_OUTLINE
Definition: nuklear.h:283
@ NK_SYMBOL_MINUS
Definition: nuklear.h:289
@ NK_SYMBOL_RECT_SOLID
Definition: nuklear.h:282
@ NK_SYMBOL_TRIANGLE_RIGHT
Definition: nuklear.h:287
@ NK_SYMBOL_PLUS
Definition: nuklear.h:288
NK_API void nk_property_float(struct nk_context *, const char *name, float min, float *val, float max, float step, float inc_per_pixel)
NK_API char * nk_str_get(struct nk_str *)
NK_API void nk_text_wrap_colored(struct nk_context *, const char *, int, struct nk_color)
NK_API void nk_str_remove_runes(struct nk_str *str, int len)
NK_API int nk_combo_item_label(struct nk_context *, const char *, nk_flags alignment)
NK_API int nk_str_append_str_utf8(struct nk_str *, const char *)
nk_window_flags
Definition: nuklear.h:5135
@ NK_WINDOW_PRIVATE
Definition: nuklear.h:5136
@ NK_WINDOW_CLOSED
Definition: nuklear.h:5145
@ NK_WINDOW_MINIMIZED
Definition: nuklear.h:5147
@ NK_WINDOW_HIDDEN
Definition: nuklear.h:5143
@ NK_WINDOW_ROM
Definition: nuklear.h:5139
@ NK_WINDOW_NOT_INTERACTIVE
Definition: nuklear.h:5141
@ NK_WINDOW_DYNAMIC
Definition: nuklear.h:5137
@ NK_WINDOW_REMOVE_ROM
Definition: nuklear.h:5149
NK_API struct nk_color nk_rgb_bv(const nk_byte *rgb)
NK_API struct nk_color nk_rgba_iv(const int *rgba)
NK_API void nk_layout_row(struct nk_context *, enum nk_layout_format, float height, int cols, const float *ratio)
NK_API int nk_window_is_closed(struct nk_context *, const char *)
NK_API void nk_chart_end(struct nk_context *)
NK_API float nk_window_get_height(const struct nk_context *)
#define NK_CLAMP(i, v, x)
Definition: nuklear.h:87
NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva)
#define NK_SCROLLBAR_HIDING_TIMEOUT
Definition: nuklear.h:26
NK_API int nk_button_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags text_alignment)
void(* nk_command_custom_callback)(void *canvas, short x, short y, unsigned short w, unsigned short h, nk_handle callback_data)
Definition: nuklear.h:4318
NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags)
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
#define NK_LIB
Definition: nuklear.h:52
NK_API int nk_input_is_mouse_down(const struct nk_input *, enum nk_buttons)
NK_API struct nk_color nk_rgb_cf(struct nk_colorf c)
NK_API int nk_menu_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
#define NK_TEXTEDIT_UNDOCHARCOUNT
Definition: nuklear.h:4026
NK_API struct nk_color nk_rgb_f(float r, float g, float b)
nk_style_item_type
Definition: nuklear.h:4588
@ NK_STYLE_ITEM_IMAGE
Definition: nuklear.h:4590
@ NK_STYLE_ITEM_COLOR
Definition: nuklear.h:4589
NK_API void nk_window_get_scroll(struct nk_context *, nk_uint *offset_x, nk_uint *offset_y)
#define NK_FLAGS_STACK_SIZE
Definition: nuklear.h:5264
NK_API const char * nk_style_get_color_by_name(enum nk_style_colors)
NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed)
nk_buttons
Definition: nuklear.h:553
@ NK_BUTTON_LEFT
Definition: nuklear.h:554
@ NK_BUTTON_DOUBLE
Definition: nuklear.h:557
@ NK_BUTTON_MIDDLE
Definition: nuklear.h:555
@ NK_BUTTON_MAX
Definition: nuklear.h:558
@ NK_BUTTON_RIGHT
Definition: nuklear.h:556
NK_API int nk_chart_begin(struct nk_context *, enum nk_chart_type, int num, float min, float max)
NK_POINTER_TYPE nk_ptr
Definition: nuklear.h:189
NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region)
NK_API void nk_style_show_cursor(struct nk_context *)
NK_API void nk_fill_rect_multi_color(struct nk_command_buffer *, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom)
NK_API int nk_button_label_styled(struct nk_context *, const struct nk_style_button *, const char *title)
NK_API int nk_input_has_mouse_click(const struct nk_input *, enum nk_buttons)
NK_API int nk_option_text(struct nk_context *, const char *, int, int active)
#define NK_UTF_INVALID
Definition: nuklear.h:5397
nk_show_states
Definition: nuklear.h:257
@ NK_HIDDEN
Definition: nuklear.h:257
@ NK_SHOWN
Definition: nuklear.h:257
NK_API struct nk_vec2 nk_widget_position(struct nk_context *)
#define NK_LEN(a)
Definition: nuklear.h:5402
NK_API int nk_style_pop_flags(struct nk_context *)
NK_API int nk_utf_encode(nk_rune, char *, int)
nk_text_edit_type
Definition: nuklear.h:4052
@ NK_TEXT_EDIT_SINGLE_LINE
Definition: nuklear.h:4053
@ NK_TEXT_EDIT_MULTI_LINE
Definition: nuklear.h:4054
char nk_glyph[NK_UTF_SIZE]
Definition: nuklear.h:246
NK_API int nk_menu_begin_symbol(struct nk_context *, const char *, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_popup_close(struct nk_context *)
NK_API char * nk_str_at_rune(struct nk_str *, int pos, nk_rune *unicode, int *len)
NK_API nk_flags nk_chart_push(struct nk_context *, float)
NK_API void nk_window_set_scroll(struct nk_context *, nk_uint offset_x, nk_uint offset_y)
NK_API int nk_combo_item_text(struct nk_context *, const char *, int, nk_flags alignment)
NK_API struct nk_panel * nk_window_get_panel(struct nk_context *)
NK_API int nk_menu_begin_symbol_text(struct nk_context *, const char *, int, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
NK_API int nk_strfilter(const char *text, const char *regexp)
NK_API void nk_group_scrolled_end(struct nk_context *)
NK_API int nk_contextual_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
NK_INT16 nk_short
Definition: nuklear.h:184
NK_API void nk_buffer_push(struct nk_buffer *, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align)
NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
#define NK_TEXTEDIT_UNDOSTATECOUNT
Definition: nuklear.h:4022
NK_API void nk_textedit_delete(struct nk_text_edit *, int where, int len)
NK_API void nk_layout_row_template_push_dynamic(struct nk_context *)
NK_API void nk_label_colored_wrap(struct nk_context *, const char *, struct nk_color)
#define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)
Definition: nuklear.h:5271
NK_API const struct nk_command * nk__begin(struct nk_context *)
NK_API int nk_utf_decode(const char *, nk_rune *, int)
NK_API int nk_tree_element_image_push_hashed(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len, int seed)
NK_API void nk_button_set_behavior(struct nk_context *, enum nk_button_behavior)
#define NK_INT16
Definition: nuklear.h:130
NK_API struct nk_color nk_hsv_fv(const float *hsv)
NK_API void nk_group_get_scroll(struct nk_context *, const char *id, nk_uint *x_offset, nk_uint *y_offset)
NK_API int nk_button_image(struct nk_context *, struct nk_image img)
#define NK_ABS(a)
Definition: nuklear.h:5403
NK_API void nk_str_init(struct nk_str *, const struct nk_allocator *, nk_size size)
#define NK_STATIC_ASSERT(exp)
Definition: nuklear.h:74
NK_API int nk_style_push_color(struct nk_context *, struct nk_color *, struct nk_color)
NK_API struct nk_colorf nk_hsva_colorfv(float *c)
NK_API int nk_combo_begin_label(struct nk_context *, const char *selected, struct nk_vec2 size)
NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in)
NK_API int nk_str_append_text_utf8(struct nk_str *, const char *, int)
NK_API int nk_button_symbol(struct nk_context *, enum nk_symbol_type)
NK_API int nk_combo_begin_color(struct nk_context *, struct nk_color color, struct nk_vec2 size)
NK_API int nk_str_append_str_runes(struct nk_str *, const nk_rune *)
#define NK_POINTER_TYPE
Definition: nuklear.h:176
NK_API int nk_menu_begin_label(struct nk_context *, const char *, nk_flags align, struct nk_vec2 size)
NK_API int nk_input_mouse_clicked(const struct nk_input *, enum nk_buttons, struct nk_rect)
NK_API void nk_stroke_circle(struct nk_command_buffer *, struct nk_rect, float line_thickness, struct nk_color)
NK_API int nk_selectable_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int *value)
#define NK_UTF_SIZE
Definition: nuklear.h:18
NK_API void nk_input_unicode(struct nk_context *, nk_rune)
NK_API int nk_contextual_begin(struct nk_context *, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds)
NK_API void nk_str_init_fixed(struct nk_str *, void *memory, nk_size size)
#define NK_ALIGN_PTR(x, mask)
Definition: nuklear.h:5439
NK_API void nk_text(struct nk_context *, const char *, int, nk_flags)
NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect *, struct nk_context *, struct nk_vec2)
NK_API int nk_menu_item_label(struct nk_context *, const char *, nk_flags alignment)
NK_API int nk_checkbox_label(struct nk_context *, const char *, int *active)
NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context *, struct nk_rect)
NK_API int nk_filter_ascii(const struct nk_text_edit *, nk_rune unicode)
void(* nk_plugin_paste)(nk_handle, struct nk_text_edit *)
Definition: nuklear.h:268
NK_API void nk_input_button(struct nk_context *, enum nk_buttons, int x, int y, int down)
NK_API int nk_style_pop_font(struct nk_context *)
NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color)
nk_modify
Definition: nuklear.h:254
@ NK_FIXED
Definition: nuklear.h:254
@ NK_MODIFIABLE
Definition: nuklear.h:254
NK_API void nk_property_double(struct nk_context *, const char *name, double min, double *val, double max, double step, float inc_per_pixel)
NK_API int nk_widget_is_hovered(struct nk_context *)
NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context *)
NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color)
NK_API void nk_edit_unfocus(struct nk_context *)
NK_API int nk_button_pop_behavior(struct nk_context *)
NK_API int nk_menu_begin_image_text(struct nk_context *, const char *, int, nk_flags align, struct nk_image, struct nk_vec2 size)
nk_tree_type
Definition: nuklear.h:263
@ NK_TREE_NODE
Definition: nuklear.h:263
@ NK_TREE_TAB
Definition: nuklear.h:263
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color)
NK_API int nk_option_label(struct nk_context *, const char *, int active)
NK_API float nk_slide_float(struct nk_context *, float min, float val, float max, float step)
NK_API int nk_strtoi(const char *str, const char **endptr)
NK_API int nk_combo_string(struct nk_context *, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_stricmp(const char *s1, const char *s2)
NK_API int nk_tree_push_hashed(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
NK_API void nk_tree_element_pop(struct nk_context *)
NK_API int nk_window_is_any_hovered(struct nk_context *)
NK_API int nk_str_append_str_char(struct nk_str *, const char *)
NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
NK_API void nk_style_load_cursor(struct nk_context *, enum nk_style_cursor, const struct nk_cursor *)
NK_API int nk_str_len(struct nk_str *)
NK_API void nk_layout_row_template_push_static(struct nk_context *, float width)
NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color)
NK_API void nk_color_hex_rgb(char *output, struct nk_color)
NK_API int nk_list_view_begin(struct nk_context *, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count)
NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color)
#define NK_BUTTON_BEHAVIOR_STACK_SIZE
Definition: nuklear.h:5244
NK_API void nk_window_collapse_if(struct nk_context *, const char *name, enum nk_collapse_states, int cond)
NK_API int nk_contextual_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
NK_API void nk_window_show_if(struct nk_context *, const char *name, enum nk_show_states, int cond)
NK_API void nk_list_view_end(struct nk_list_view *)
NK_API struct nk_rect nk_rectiv(const int *xywh)
NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align)
NK_API struct nk_vec2 nk_vec2v(const float *xy)
NK_API void nk_str_delete_chars(struct nk_str *, int pos, int len)
NK_API int nk_combo_begin_symbol(struct nk_context *, enum nk_symbol_type, struct nk_vec2 size)
NK_API struct nk_color nk_hsva_fv(const float *hsva)
#define NK_INPUT_MAX
Definition: nuklear.h:20
NK_API int nk_contextual_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
nk_command_clipping
Definition: nuklear.h:4340
@ NK_CLIPPING_OFF
Definition: nuklear.h:4341
@ NK_CLIPPING_ON
Definition: nuklear.h:4342
NK_API void nk_menubar_end(struct nk_context *)
NK_API int nk_str_insert_str_runes(struct nk_str *, int pos, const nk_rune *)
NK_API void nk_spacing(struct nk_context *, int cols)
nk_text_alignment
Definition: nuklear.h:2863
@ NK_TEXT_CENTERED
Definition: nuklear.h:2865
@ NK_TEXT_RIGHT
Definition: nuklear.h:2866
@ NK_TEXT_LEFT
Definition: nuklear.h:2864
NK_API int nk_style_pop_float(struct nk_context *)
NK_API void nk_style_default(struct nk_context *)
NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
NK_API struct nk_rect nk_recti(int x, int y, int w, int h)
NK_API void nk_stroke_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color)
nk_uint nk_rune
Definition: nuklear.h:193
#define nk_zero_struct(s)
Definition: nuklear.h:5419
NK_API int nk_filter_oct(const struct nk_text_edit *, nk_rune unicode)
NK_API void nk_label(struct nk_context *, const char *, nk_flags align)
NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context *, struct nk_rect)
NK_API struct nk_image nk_image_ptr(void *)
NK_API const char * nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len)
NK_API int nk_strlen(const char *str)
NK_API void nk_buffer_free(struct nk_buffer *)
NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
NK_API struct nk_command_buffer * nk_window_get_canvas(struct nk_context *)
NK_API int nk_check_text(struct nk_context *, const char *, int, int active)
NK_API void nk_style_load_all_cursors(struct nk_context *, struct nk_cursor *)
NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context *)
#define NK_INTERN
Definition: nuklear.h:56
NK_API void nk_stroke_triangle(struct nk_command_buffer *, float, float, float, float, float, float, float line_thichness, struct nk_color)
NK_API const struct nk_command * nk__next(struct nk_context *, const struct nk_command *)
NK_API int nk_style_push_style_item(struct nk_context *, struct nk_style_item *, struct nk_style_item)
NK_API void nk_tooltip(struct nk_context *, const char *)
NK_API int nk_style_push_font(struct nk_context *, const struct nk_user_font *)
NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value)
NK_API nk_handle nk_handle_id(int)
#define NK_SATURATE(x)
Definition: nuklear.h:5401
int(* nk_plugin_filter)(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:267
NK_API int nk_button_image_label_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, nk_flags text_alignment)
NK_API int nk_str_insert_at_rune(struct nk_str *, int pos, const char *, int)
NK_API void nk_combo_end(struct nk_context *)
NK_API int nk_str_insert_text_utf8(struct nk_str *, int pos, const char *, int)
nk_color_format
Definition: nuklear.h:260
@ NK_RGB
Definition: nuklear.h:260
@ NK_RGBA
Definition: nuklear.h:260
NK_API int nk_widget_is_mouse_clicked(struct nk_context *, enum nk_buttons)
NK_API void nk_buffer_init(struct nk_buffer *, const struct nk_allocator *, nk_size size)
nk_style_colors
Definition: nuklear.h:3344
@ NK_COLOR_HEADER
Definition: nuklear.h:3347
@ NK_COLOR_CHART
Definition: nuklear.h:3365
@ NK_COLOR_SCROLLBAR_CURSOR_ACTIVE
Definition: nuklear.h:3371
@ NK_COLOR_SLIDER_CURSOR_ACTIVE
Definition: nuklear.h:3360
@ NK_COLOR_EDIT_CURSOR
Definition: nuklear.h:3363
@ NK_COLOR_SELECT_ACTIVE
Definition: nuklear.h:3356
@ NK_COLOR_TEXT
Definition: nuklear.h:3345
@ NK_COLOR_BUTTON_ACTIVE
Definition: nuklear.h:3351
@ NK_COLOR_SELECT
Definition: nuklear.h:3355
@ NK_COLOR_TOGGLE_CURSOR
Definition: nuklear.h:3354
@ NK_COLOR_SCROLLBAR_CURSOR
Definition: nuklear.h:3369
@ NK_COLOR_BUTTON
Definition: nuklear.h:3349
@ NK_COLOR_SLIDER_CURSOR_HOVER
Definition: nuklear.h:3359
@ NK_COLOR_CHART_COLOR_HIGHLIGHT
Definition: nuklear.h:3367
@ NK_COLOR_CHART_COLOR
Definition: nuklear.h:3366
@ NK_COLOR_SCROLLBAR
Definition: nuklear.h:3368
@ NK_COLOR_SLIDER
Definition: nuklear.h:3357
@ NK_COLOR_EDIT
Definition: nuklear.h:3362
@ NK_COLOR_COUNT
Definition: nuklear.h:3373
@ NK_COLOR_BUTTON_HOVER
Definition: nuklear.h:3350
@ NK_COLOR_TOGGLE_HOVER
Definition: nuklear.h:3353
@ NK_COLOR_SCROLLBAR_CURSOR_HOVER
Definition: nuklear.h:3370
@ NK_COLOR_WINDOW
Definition: nuklear.h:3346
@ NK_COLOR_COMBO
Definition: nuklear.h:3364
@ NK_COLOR_BORDER
Definition: nuklear.h:3348
@ NK_COLOR_TOGGLE
Definition: nuklear.h:3352
@ NK_COLOR_TAB_HEADER
Definition: nuklear.h:3372
@ NK_COLOR_SLIDER_CURSOR
Definition: nuklear.h:3358
@ NK_COLOR_PROPERTY
Definition: nuklear.h:3361
NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags)
NK_API void nk_buffer_reset(struct nk_buffer *, enum nk_buffer_allocation_type type)
NK_API void nk_popup_get_scroll(struct nk_context *, nk_uint *offset_x, nk_uint *offset_y)
#define NK_UINT32
Definition: nuklear.h:146
#define NK_PTR_TO_UINT(x)
Definition: nuklear.h:5430
#define NK_CONFIG_STACK(type, size)
Definition: nuklear.h:5276
NK_API void * nk_buffer_memory(struct nk_buffer *)
NK_API void nk_buffer_init_fixed(struct nk_buffer *, void *memory, nk_size size)
#define NK_FONT_STACK_SIZE
Definition: nuklear.h:5248
NK_API int nk_str_len_char(struct nk_str *)
NK_API void nk_combobox_string(struct nk_context *, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input *, struct nk_rect)
NK_API int nk_filter_decimal(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_textedit_paste(struct nk_text_edit *, char const *, int len)
NK_SIZE_TYPE nk_size
Definition: nuklear.h:188
#define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
Definition: nuklear.h:5029
NK_API const void * nk_buffer_memory_const(const struct nk_buffer *)
NK_API void nk_layout_row_template_end(struct nk_context *)
NK_API nk_size nk_prog(struct nk_context *, nk_size cur, nk_size max, int modifyable)
NK_API int nk_button_image_text_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, int, nk_flags alignment)
NK_API int nk_combo_item_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags alignment)
NK_API int nk_progress(struct nk_context *, nk_size *cur, nk_size max, int modifyable)
NK_API void nk_menubar_begin(struct nk_context *)
NK_API int nk_str_insert_str_char(struct nk_str *, int pos, const char *)
NK_API struct nk_image nk_image_id(int)
NK_API int nk_filter_float(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_style_pop_color(struct nk_context *)
NK_API void nk_layout_reset_min_row_height(struct nk_context *)
nk_widget_states
Definition: nuklear.h:2829
@ NK_WIDGET_STATE_MODIFIED
Definition: nuklear.h:2830
@ NK_WIDGET_STATE_LEFT
Definition: nuklear.h:2835
@ NK_WIDGET_STATE_ACTIVED
Definition: nuklear.h:2834
@ NK_WIDGET_STATE_ENTERED
Definition: nuklear.h:2832
@ NK_WIDGET_STATE_HOVER
Definition: nuklear.h:2833
@ NK_WIDGET_STATE_ACTIVE
Definition: nuklear.h:2837
@ NK_WIDGET_STATE_HOVERED
Definition: nuklear.h:2836
@ NK_WIDGET_STATE_INACTIVE
Definition: nuklear.h:2831
nk_collapse_states
Definition: nuklear.h:256
@ NK_MINIMIZED
Definition: nuklear.h:256
@ NK_MAXIMIZED
Definition: nuklear.h:256
#define NK_STYLE_ITEM_STACK_SIZE
Definition: nuklear.h:5252
NK_API int nk_init_fixed(struct nk_context *, void *memory, nk_size size, const struct nk_user_font *)
NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba)
#define NK_VALUE_PAGE_CAPACITY
Definition: nuklear.h:5312
NK_API void nk_textedit_redo(struct nk_text_edit *)
#define NK_INT32
Definition: nuklear.h:139
#define nk_vec2_muls(a, t)
Definition: nuklear.h:5415
NK_API const char * nk_str_get_const(const struct nk_str *)
NK_API float nk_strtof(const char *str, const char **endptr)
NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
NK_API void nk_window_collapse(struct nk_context *, const char *name, enum nk_collapse_states state)
NK_API int nk_widget_has_mouse_click_down(struct nk_context *, enum nk_buttons, int down)
NK_API struct nk_vec2 nk_vec2(float x, float y)
#define NK_INBOX(px, py, x, y, w, h)
Definition: nuklear.h:5405
#define NK_ALIGN_PTR_BACK(x, mask)
Definition: nuklear.h:5441
NK_API int nk_radio_label(struct nk_context *, const char *, int *active)
NK_API void nk_textedit_select_all(struct nk_text_edit *)
NK_API void nk_image_color(struct nk_context *, struct nk_image, struct nk_color)
NK_UINT32 nk_uint
Definition: nuklear.h:187
NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx)
NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color)
#define NK_COLOR_STACK_SIZE
Definition: nuklear.h:5268
NK_API int nk_str_insert_text_runes(struct nk_str *, int pos, const nk_rune *, int)
NK_API struct nk_colorf nk_color_cf(struct nk_color)
NK_API void nk_text_wrap(struct nk_context *, const char *, int)
float(* nk_text_width_f)(nk_handle, float h, const char *, int len)
Definition: nuklear.h:3679
NK_API int nk_selectable_label(struct nk_context *, const char *, nk_flags align, int *value)
NK_API int nk_str_insert_str_utf8(struct nk_str *, int pos, const char *)
NK_API int nk_window_has_focus(const struct nk_context *)
NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context *, struct nk_vec2)
NK_API nk_flags nk_chart_push_slot(struct nk_context *, float, int)
NK_API int nk_checkbox_flags_text(struct nk_context *, const char *, int, unsigned int *flags, unsigned int value)
NK_API void nk_push_custom(struct nk_command_buffer *, struct nk_rect, nk_command_custom_callback, nk_handle usr)
nk_text_align
Definition: nuklear.h:2855
@ NK_TEXT_ALIGN_BOTTOM
Definition: nuklear.h:2861
@ NK_TEXT_ALIGN_MIDDLE
Definition: nuklear.h:2860
@ NK_TEXT_ALIGN_CENTERED
Definition: nuklear.h:2857
@ NK_TEXT_ALIGN_RIGHT
Definition: nuklear.h:2858
@ NK_TEXT_ALIGN_TOP
Definition: nuklear.h:2859
@ NK_TEXT_ALIGN_LEFT
Definition: nuklear.h:2856
NK_API int nk_checkbox_text(struct nk_context *, const char *, int, int *active)
NK_API struct nk_color nk_hsv_f(float h, float s, float v)
nk_anti_aliasing
Definition: nuklear.h:925
@ NK_ANTI_ALIASING_ON
Definition: nuklear.h:925
@ NK_ANTI_ALIASING_OFF
Definition: nuklear.h:925
NK_API int nk_style_push_flags(struct nk_context *, nk_flags *, nk_flags)
NK_API struct nk_rect nk_widget_bounds(struct nk_context *)
NK_API void nk_combobox_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *, int *selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_str_append_text_runes(struct nk_str *, const nk_rune *, int)
NK_API int nk_tree_state_push(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states *state)
NK_API void nk_combo_close(struct nk_context *)
#define nk_vec2_sub(a, b)
Definition: nuklear.h:5412
NK_API float nk_layout_ratio_from_pixel(struct nk_context *, float pixel_width)
NK_API unsigned nk_check_flags_label(struct nk_context *, const char *, unsigned int flags, unsigned int value)
NK_API int nk_tree_state_image_push(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state)
NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a)
#define nk_ptr_add_const(t, p, i)
Definition: nuklear.h:5418
NK_API void nk_tooltip_end(struct nk_context *)
NK_API void nk_layout_set_min_row_height(struct nk_context *, float height)
NK_API void nk_push_scissor(struct nk_command_buffer *, struct nk_rect)
NK_API void nk_stroke_curve(struct nk_command_buffer *, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color)
NK_API int nk_menu_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
#define NK_GLOBAL
Definition: nuklear.h:58
nk_text_edit_mode
Definition: nuklear.h:4057
@ NK_TEXT_EDIT_MODE_VIEW
Definition: nuklear.h:4058
@ NK_TEXT_EDIT_MODE_REPLACE
Definition: nuklear.h:4060
@ NK_TEXT_EDIT_MODE_INSERT
Definition: nuklear.h:4059
NK_API int nk_selectable_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int *value)
NK_API void nk_textedit_text(struct nk_text_edit *, const char *, int total_len)
NK_API void nk_fill_polygon(struct nk_command_buffer *, float *, int point_count, struct nk_color)
NK_API int nk_style_push_vec2(struct nk_context *, struct nk_vec2 *, struct nk_vec2)
nk_edit_types
Definition: nuklear.h:3213
@ NK_EDIT_SIMPLE
Definition: nuklear.h:3214
@ NK_EDIT_FIELD
Definition: nuklear.h:3215
@ NK_EDIT_EDITOR
Definition: nuklear.h:3217
@ NK_EDIT_BOX
Definition: nuklear.h:3216
void(* nk_plugin_free)(nk_handle, void *old)
Definition: nuklear.h:266
NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols)
NK_API nk_flags nk_edit_string(struct nk_context *, nk_flags, char *buffer, int *len, int max, nk_plugin_filter)
NK_API void nk_stroke_polyline(struct nk_command_buffer *, float *points, int point_count, float line_thickness, struct nk_color col)
NK_API int nk_button_symbol_text_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API void nk_style_hide_cursor(struct nk_context *)
nk_allocation_type
Definition: nuklear.h:3884
@ NK_BUFFER_FIXED
Definition: nuklear.h:3885
@ NK_BUFFER_DYNAMIC
Definition: nuklear.h:3886
NK_API int nk_menu_item_text(struct nk_context *, const char *, int, nk_flags align)
nk_button_behavior
Definition: nuklear.h:253
@ NK_BUTTON_DEFAULT
Definition: nuklear.h:253
@ NK_BUTTON_REPEATER
Definition: nuklear.h:253
NK_API struct nk_colorf nk_color_picker(struct nk_context *, struct nk_colorf, enum nk_color_format)
NK_API void nk_window_set_size(struct nk_context *, const char *name, struct nk_vec2)
NK_API struct nk_vec2 nk_window_get_size(const struct nk_context *)
#define nk_foreach(c, ctx)
Definition: nuklear.h:993
NK_API int nk_menu_begin_image_label(struct nk_context *, const char *, nk_flags align, struct nk_image, struct nk_vec2 size)
NK_API struct nk_color nk_hsva(int h, int s, int v, int a)
NK_API enum nk_widget_layout_states nk_widget(struct nk_rect *, const struct nk_context *)
NK_API void nk_layout_space_push(struct nk_context *, struct nk_rect bounds)
NK_API struct nk_vec2 nk_widget_size(struct nk_context *)
NK_API struct nk_color nk_rgba_u32(nk_uint)
NK_API void nk_group_set_scroll(struct nk_context *, const char *id, nk_uint x_offset, nk_uint y_offset)
#define NK_SIZE_TYPE
Definition: nuklear.h:161
NK_API double nk_strtod(const char *str, const char **endptr)
NK_API void nk_fill_triangle(struct nk_command_buffer *, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color)
NK_API struct nk_vec2 nk_rect_size(struct nk_rect)
NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input *, struct nk_rect)
NK_API void nk_layout_row_template_begin(struct nk_context *, float row_height)
NK_API int nk_select_text(struct nk_context *, const char *, int, nk_flags align, int value)
NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color)
NK_API int nk_input_is_key_released(const struct nk_input *, enum nk_keys)
NK_API void nk_tree_state_pop(struct nk_context *)
NK_API void nk_color_fv(float *rgba_out, struct nk_color)
NK_API void nk_layout_row_push(struct nk_context *, float value)
NK_API void nk_input_char(struct nk_context *, char)
NK_API void nk_str_clear(struct nk_str *)
NK_API int nk_combo_begin_symbol_text(struct nk_context *, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size)
void(* nk_query_font_glyph_f)(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
Definition: nuklear.h:3680
NK_API int nk_image_is_subimage(const struct nk_image *img)
NK_API void nk_plot(struct nk_context *, enum nk_chart_type, const float *values, int count, int offset)
NK_API struct nk_rect nk_rectv(const float *xywh)
NK_API int nk_init(struct nk_context *, struct nk_allocator *, const struct nk_user_font *)
NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input *, struct nk_rect)
NK_API int nk_combo_begin_image_text(struct nk_context *, const char *selected, int, struct nk_image, struct nk_vec2 size)
NK_API void nk_input_scroll(struct nk_context *, struct nk_vec2 val)
#define NK_MIN(a, b)
Definition: nuklear.h:85
NK_API struct nk_vec2 nk_vec2i(int x, int y)
#define NK_UINT16
Definition: nuklear.h:133
NK_API void nk_text_colored(struct nk_context *, const char *, int, nk_flags, struct nk_color)
nk_widget_layout_states
Definition: nuklear.h:2824
@ NK_WIDGET_ROM
Definition: nuklear.h:2827
@ NK_WIDGET_VALID
Definition: nuklear.h:2826
@ NK_WIDGET_INVALID
Definition: nuklear.h:2825
NK_API void nk_textedit_delete_selection(struct nk_text_edit *)
#define NK_BETWEEN(x, a, b)
Definition: nuklear.h:5404
nk_command_type
Definition: nuklear.h:4157
@ NK_COMMAND_RECT_FILLED
Definition: nuklear.h:4163
@ NK_COMMAND_POLYLINE
Definition: nuklear.h:4173
@ NK_COMMAND_SCISSOR
Definition: nuklear.h:4159
@ NK_COMMAND_POLYGON_FILLED
Definition: nuklear.h:4172
@ NK_COMMAND_ARC
Definition: nuklear.h:4167
@ NK_COMMAND_TRIANGLE_FILLED
Definition: nuklear.h:4170
@ NK_COMMAND_RECT
Definition: nuklear.h:4162
@ NK_COMMAND_POLYGON
Definition: nuklear.h:4171
@ NK_COMMAND_NOP
Definition: nuklear.h:4158
@ NK_COMMAND_CUSTOM
Definition: nuklear.h:4176
@ NK_COMMAND_CURVE
Definition: nuklear.h:4161
@ NK_COMMAND_CIRCLE
Definition: nuklear.h:4165
@ NK_COMMAND_IMAGE
Definition: nuklear.h:4175
@ NK_COMMAND_TRIANGLE
Definition: nuklear.h:4169
@ NK_COMMAND_TEXT
Definition: nuklear.h:4174
@ NK_COMMAND_LINE
Definition: nuklear.h:4160
@ NK_COMMAND_CIRCLE_FILLED
Definition: nuklear.h:4166
@ NK_COMMAND_RECT_MULTI_COLOR
Definition: nuklear.h:4164
@ NK_COMMAND_ARC_FILLED
Definition: nuklear.h:4168
NK_API void nk_combobox(struct nk_context *, const char **items, int count, int *selected, int item_height, struct nk_vec2 size)
NK_API int nk_button_color(struct nk_context *, struct nk_color)
NK_API int nk_button_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API struct nk_color nk_rgb_iv(const int *rgb)
NK_API int nk_str_append_text_char(struct nk_str *, const char *, int)
nk_popup_type
Definition: nuklear.h:261
@ NK_POPUP_DYNAMIC
Definition: nuklear.h:261
@ NK_POPUP_STATIC
Definition: nuklear.h:261
NK_API double nk_propertyd(struct nk_context *, const char *name, double min, double val, double max, double step, float inc_per_pixel)
NK_API int nk_menu_begin_symbol_label(struct nk_context *, const char *, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
#define nk_vec2_len_sqr(a)
Definition: nuklear.h:5414
NK_API int nk_menu_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API void nk_textedit_init_fixed(struct nk_text_edit *, void *memory, nk_size size)
NK_API int nk_button_symbol_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type)
nk_style_cursor
Definition: nuklear.h:3375
@ NK_CURSOR_TEXT
Definition: nuklear.h:3377
@ NK_CURSOR_MOVE
Definition: nuklear.h:3378
@ NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT
Definition: nuklear.h:3382
@ NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT
Definition: nuklear.h:3381
@ NK_CURSOR_RESIZE_HORIZONTAL
Definition: nuklear.h:3380
@ NK_CURSOR_COUNT
Definition: nuklear.h:3383
@ NK_CURSOR_ARROW
Definition: nuklear.h:3376
@ NK_CURSOR_RESIZE_VERTICAL
Definition: nuklear.h:3379
NK_API int nk_button_image_text(struct nk_context *, struct nk_image img, const char *, int, nk_flags alignment)
NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in)
NK_API void nk_style_from_table(struct nk_context *, const struct nk_color *)
NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color)
NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down)
NK_API int nk_color_pick(struct nk_context *, struct nk_colorf *, enum nk_color_format)
NK_API int nk_style_push_float(struct nk_context *, float *, float)
NK_API int nk_chart_begin_colored(struct nk_context *, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max)
NK_API int nk_select_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags align, int value)
#define NK_CHART_MAX_SLOT
Definition: nuklear.h:5032
NK_API int nk_window_is_active(struct nk_context *, const char *)
NK_API int nk_group_scrolled_begin(struct nk_context *, struct nk_scroll *off, const char *title, nk_flags)
NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value)
#define nk_ptr_add(t, p, i)
Definition: nuklear.h:5417
NK_API void nk_input_motion(struct nk_context *, int x, int y)
NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color)
NK_API void nk_layout_space_begin(struct nk_context *, enum nk_layout_format, float height, int widget_count)
#define NK_INT8
Definition: nuklear.h:124
NK_API int nk_combo_begin_symbol_label(struct nk_context *, const char *selected, enum nk_symbol_type, struct nk_vec2 size)
NK_API int nk_menu_begin_image(struct nk_context *, const char *, struct nk_image, struct nk_vec2 size)
#define NK_MAX(a, b)
Definition: nuklear.h:86
NK_API void nk_window_set_position(struct nk_context *, const char *name, struct nk_vec2 pos)
NK_API void nk_color_hex_rgba(char *output, struct nk_color)
NK_API int nk_str_insert_text_char(struct nk_str *, int pos, const char *, int)
NK_API int nk_button_image_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img)
NK_API void nk_window_set_focus(struct nk_context *, const char *name)
NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color)
NK_API int nk_selectable_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags align, int *value)
NK_API const char * nk_str_at_char_const(const struct nk_str *, int pos)
NK_API int nk_selectable_text(struct nk_context *, const char *, int, nk_flags align, int *value)
NK_API struct nk_color nk_rgba_cf(struct nk_colorf c)
NK_API int nk_combo_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
NK_UINT16 nk_ushort
Definition: nuklear.h:185
nk_panel_flags
Definition: nuklear.h:1233
@ NK_WINDOW_TITLE
Definition: nuklear.h:1240
@ NK_WINDOW_SCALABLE
Definition: nuklear.h:1236
@ NK_WINDOW_SCALE_LEFT
Definition: nuklear.h:1243
@ NK_WINDOW_MOVABLE
Definition: nuklear.h:1235
@ NK_WINDOW_MINIMIZABLE
Definition: nuklear.h:1238
@ NK_WINDOW_CLOSABLE
Definition: nuklear.h:1237
@ NK_WINDOW_BORDER
Definition: nuklear.h:1234
@ NK_WINDOW_BACKGROUND
Definition: nuklear.h:1242
@ NK_WINDOW_NO_INPUT
Definition: nuklear.h:1244
@ NK_WINDOW_NO_SCROLLBAR
Definition: nuklear.h:1239
@ NK_WINDOW_SCROLL_AUTO_HIDE
Definition: nuklear.h:1241
NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context *)
NK_API struct nk_style_item nk_style_item_color(struct nk_color)
#define NK_MAX_NUMBER_BUFFER
Definition: nuklear.h:23
NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color)
#define NK_UNUSED(x)
Definition: nuklear.h:5400
NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect, int down)
NK_API struct nk_image nk_subimage_ptr(void *, unsigned short w, unsigned short h, struct nk_rect sub_region)
NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score)
NK_API int nk_group_begin(struct nk_context *, const char *title, nk_flags)
NK_API void nk_textedit_free(struct nk_text_edit *)
nk_buffer_allocation_type
Definition: nuklear.h:3889
@ NK_BUFFER_BACK
Definition: nuklear.h:3891
@ NK_BUFFER_MAX
Definition: nuklear.h:3892
@ NK_BUFFER_FRONT
Definition: nuklear.h:3890
NK_API int nk_window_is_hovered(struct nk_context *)
NK_API int nk_combo_begin_text(struct nk_context *, const char *selected, int, struct nk_vec2 size)
NK_API void nk_buffer_info(struct nk_memory_status *, struct nk_buffer *)
NK_API void nk_clear(struct nk_context *)
NK_API int nk_style_pop_vec2(struct nk_context *)
nk_style_header_align
Definition: nuklear.h:4929
@ NK_HEADER_RIGHT
Definition: nuklear.h:4931
@ NK_HEADER_LEFT
Definition: nuklear.h:4930
NK_API int nk_contextual_item_label(struct nk_context *, const char *, nk_flags align)
NK_API void nk_label_colored(struct nk_context *, const char *, nk_flags align, struct nk_color)
NK_API void nk_end(struct nk_context *ctx)
NK_API int nk_window_is_hidden(struct nk_context *, const char *)
NK_API void nk_fill_circle(struct nk_command_buffer *, struct nk_rect, struct nk_color)
NK_API void nk_group_end(struct nk_context *)
NK_API void nk_str_remove_chars(struct nk_str *, int len)
NK_API int nk_menu_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
NK_API void nk_window_show(struct nk_context *, const char *name, enum nk_show_states)
#define NK_PI
Definition: nuklear.h:5396
NK_API int nk_combo_begin_image(struct nk_context *, struct nk_image img, struct nk_vec2 size)
NK_API float nk_widget_height(struct nk_context *)
#define NK_FLOAT_STACK_SIZE
Definition: nuklear.h:5256
#define NK_MAX_FLOAT_PRECISION
Definition: nuklear.h:5398
NK_API int nk_combo_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
nk_panel_type
Definition: nuklear.h:5035
@ NK_PANEL_NONE
Definition: nuklear.h:5036
@ NK_PANEL_WINDOW
Definition: nuklear.h:5037
@ NK_PANEL_POPUP
Definition: nuklear.h:5039
@ NK_PANEL_CONTEXTUAL
Definition: nuklear.h:5040
@ NK_PANEL_GROUP
Definition: nuklear.h:5038
@ NK_PANEL_TOOLTIP
Definition: nuklear.h:5043
@ NK_PANEL_COMBO
Definition: nuklear.h:5041
@ NK_PANEL_MENU
Definition: nuklear.h:5042
NK_API void nk_stroke_polygon(struct nk_command_buffer *, float *, int point_count, float line_thickness, struct nk_color)
NK_API void nk_buffer_clear(struct nk_buffer *)
nk_layout_format
Definition: nuklear.h:262
@ NK_DYNAMIC
Definition: nuklear.h:262
@ NK_STATIC
Definition: nuklear.h:262
NK_API void nk_textedit_undo(struct nk_text_edit *)
NK_API int nk_init_custom(struct nk_context *, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *)
NK_INT32 nk_int
Definition: nuklear.h:186
NK_API int nk_select_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int value)
NK_API nk_flags nk_edit_buffer(struct nk_context *, nk_flags, struct nk_text_edit *, nk_plugin_filter)
NK_API void nk_label_wrap(struct nk_context *, const char *)
NK_API int nk_slider_float(struct nk_context *, float min, float *val, float max, float step)
NK_API void nk_draw_text(struct nk_command_buffer *, struct nk_rect, const char *text, int len, const struct nk_user_font *, struct nk_color, struct nk_color)
NK_API int nk_contextual_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API void nk_layout_row_template_push_variable(struct nk_context *, float min_width)
#define NK_WINDOW_MAX_NAME
Definition: nuklear.h:5131
NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading)
NK_API int nk_button_label(struct nk_context *, const char *title)
nk_panel_set
Definition: nuklear.h:5045
@ NK_PANEL_SET_POPUP
Definition: nuklear.h:5047
@ NK_PANEL_SET_NONBLOCK
Definition: nuklear.h:5046
@ NK_PANEL_SET_SUB
Definition: nuklear.h:5048
NK_API int nk_popup_begin(struct nk_context *, enum nk_popup_type, const char *, nk_flags, struct nk_rect bounds)
NK_API int nk_filter_binary(const struct nk_text_edit *, nk_rune unicode)
NK_API nk_rune nk_str_rune_at(const struct nk_str *, int pos)
NK_API int nk_filter_hex(const struct nk_text_edit *, nk_rune unicode)
NK_API struct nk_rect nk_rect(float x, float y, float w, float h)
NK_API struct nk_color nk_rgba(int r, int g, int b, int a)
NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color)
NK_API struct nk_style_item nk_style_item_hide(void)
nk_orientation
Definition: nuklear.h:255
@ NK_VERTICAL
Definition: nuklear.h:255
@ NK_HORIZONTAL
Definition: nuklear.h:255
NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx)
NK_API int nk_menu_begin_text(struct nk_context *, const char *title, int title_len, nk_flags align, struct nk_vec2 size)
NK_API int nk_radio_text(struct nk_context *, const char *, int, int *active)
nk_edit_events
Definition: nuklear.h:3219
@ NK_EDIT_INACTIVE
Definition: nuklear.h:3221
@ NK_EDIT_DEACTIVATED
Definition: nuklear.h:3223
@ NK_EDIT_ACTIVE
Definition: nuklear.h:3220
@ NK_EDIT_COMMITED
Definition: nuklear.h:3224
@ NK_EDIT_ACTIVATED
Definition: nuklear.h:3222
NK_API int nk_propertyi(struct nk_context *, const char *name, int min, int val, int max, int step, float inc_per_pixel)
NK_API int nk_combo(struct nk_context *, const char **items, int count, int selected, int item_height, struct nk_vec2 size)
NK_API void nk_fill_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, struct nk_color)
NK_API void nk_input_glyph(struct nk_context *, const nk_glyph)
NK_API void nk_contextual_end(struct nk_context *)
NK_UINT8 nk_uchar
Definition: nuklear.h:182
NK_API void nk_textedit_init(struct nk_text_edit *, struct nk_allocator *, nk_size size)
NK_API int nk_stricmpn(const char *s1, const char *s2, int n)
NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
NK_API struct nk_color nk_rgba_fv(const float *rgba)
#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1)
Definition: nuklear.h:5407
NK_API int nk_group_begin_titled(struct nk_context *, const char *name, const char *title, nk_flags)
NK_API int nk_combo_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
NK_API int nk_button_push_behavior(struct nk_context *, enum nk_button_behavior)
NK_API void nk_style_set_font(struct nk_context *, const struct nk_user_font *)
nk_heading
Definition: nuklear.h:252
@ NK_RIGHT
Definition: nuklear.h:252
@ NK_DOWN
Definition: nuklear.h:252
@ NK_UP
Definition: nuklear.h:252
@ NK_LEFT
Definition: nuklear.h:252
void *(* nk_plugin_alloc)(nk_handle, void *old, nk_size)
Definition: nuklear.h:265
NK_API int nk_input_is_key_down(const struct nk_input *, enum nk_keys)
NK_API int nk_tree_element_push_hashed(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len, int seed)
NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a)
Definition: nuklear.h:271
nk_handle userdata
Definition: nuklear.h:272
nk_plugin_alloc alloc
Definition: nuklear.h:273
nk_plugin_free free
Definition: nuklear.h:274
Definition: nuklear.h:3895
int active
Definition: nuklear.h:3896
nk_size offset
Definition: nuklear.h:3897
Definition: nuklear.h:3901
struct nk_allocator pool
Definition: nuklear.h:3904
struct nk_memory memory
Definition: nuklear.h:3908
enum nk_allocation_type type
Definition: nuklear.h:3906
nk_size needed
Definition: nuklear.h:3914
nk_size size
Definition: nuklear.h:3918
nk_size allocated
Definition: nuklear.h:3912
struct nk_buffer_marker marker[NK_BUFFER_MAX]
Definition: nuklear.h:3902
float grow_factor
Definition: nuklear.h:3910
nk_size calls
Definition: nuklear.h:3916
Definition: nuklear.h:5051
struct nk_color highlight
Definition: nuklear.h:5054
int count
Definition: nuklear.h:5056
struct nk_color color
Definition: nuklear.h:5053
struct nk_vec2 last
Definition: nuklear.h:5057
float max
Definition: nuklear.h:5055
enum nk_chart_type type
Definition: nuklear.h:5052
float range
Definition: nuklear.h:5055
int index
Definition: nuklear.h:5058
float min
Definition: nuklear.h:5055
Definition: nuklear.h:5061
float x
Definition: nuklear.h:5063
float h
Definition: nuklear.h:5063
int slot
Definition: nuklear.h:5062
float y
Definition: nuklear.h:5063
struct nk_chart_slot slots[NK_CHART_MAX_SLOT]
Definition: nuklear.h:5064
float w
Definition: nuklear.h:5063
Definition: nuklear.h:4030
nk_plugin_copy copy
Definition: nuklear.h:4033
nk_handle userdata
Definition: nuklear.h:4031
nk_plugin_paste paste
Definition: nuklear.h:4032
Definition: nuklear.h:240
nk_byte a
Definition: nuklear.h:240
nk_byte g
Definition: nuklear.h:240
nk_byte r
Definition: nuklear.h:240
nk_byte b
Definition: nuklear.h:240
Definition: nuklear.h:241
float r
Definition: nuklear.h:241
float g
Definition: nuklear.h:241
float b
Definition: nuklear.h:241
float a
Definition: nuklear.h:241
Definition: nuklear.h:4279
short cy
Definition: nuklear.h:4281
unsigned short r
Definition: nuklear.h:4282
struct nk_command header
Definition: nuklear.h:4280
short cx
Definition: nuklear.h:4281
struct nk_color color
Definition: nuklear.h:4284
float a[2]
Definition: nuklear.h:4283
Definition: nuklear.h:4270
struct nk_command header
Definition: nuklear.h:4271
float a[2]
Definition: nuklear.h:4275
unsigned short r
Definition: nuklear.h:4273
unsigned short line_thickness
Definition: nuklear.h:4274
struct nk_color color
Definition: nuklear.h:4276
short cx
Definition: nuklear.h:4272
short cy
Definition: nuklear.h:4272
Definition: nuklear.h:4345
nk_size end
Definition: nuklear.h:4350
struct nk_buffer * base
Definition: nuklear.h:4346
nk_size last
Definition: nuklear.h:4350
struct nk_rect clip
Definition: nuklear.h:4347
int use_clipping
Definition: nuklear.h:4348
nk_size begin
Definition: nuklear.h:4350
nk_handle userdata
Definition: nuklear.h:4349
Definition: nuklear.h:4263
struct nk_color color
Definition: nuklear.h:4267
struct nk_command header
Definition: nuklear.h:4264
unsigned short h
Definition: nuklear.h:4266
short y
Definition: nuklear.h:4265
unsigned short w
Definition: nuklear.h:4266
short x
Definition: nuklear.h:4265
Definition: nuklear.h:4255
unsigned short w
Definition: nuklear.h:4259
unsigned short line_thickness
Definition: nuklear.h:4258
struct nk_command header
Definition: nuklear.h:4256
short x
Definition: nuklear.h:4257
unsigned short h
Definition: nuklear.h:4259
struct nk_color color
Definition: nuklear.h:4260
short y
Definition: nuklear.h:4257
Definition: nuklear.h:4202
struct nk_vec2i ctrl[2]
Definition: nuklear.h:4207
struct nk_command header
Definition: nuklear.h:4203
struct nk_color color
Definition: nuklear.h:4208
struct nk_vec2i end
Definition: nuklear.h:4206
struct nk_vec2i begin
Definition: nuklear.h:4205
unsigned short line_thickness
Definition: nuklear.h:4204
Definition: nuklear.h:4320
short y
Definition: nuklear.h:4322
unsigned short w
Definition: nuklear.h:4323
struct nk_command header
Definition: nuklear.h:4321
short x
Definition: nuklear.h:4322
nk_command_custom_callback callback
Definition: nuklear.h:4325
nk_handle callback_data
Definition: nuklear.h:4324
unsigned short h
Definition: nuklear.h:4323
Definition: nuklear.h:4310
struct nk_color col
Definition: nuklear.h:4315
unsigned short h
Definition: nuklear.h:4313
struct nk_command header
Definition: nuklear.h:4311
short y
Definition: nuklear.h:4312
unsigned short w
Definition: nuklear.h:4313
short x
Definition: nuklear.h:4312
struct nk_image img
Definition: nuklear.h:4314
Definition: nuklear.h:4194
unsigned short line_thickness
Definition: nuklear.h:4196
struct nk_command header
Definition: nuklear.h:4195
struct nk_vec2i begin
Definition: nuklear.h:4197
struct nk_vec2i end
Definition: nuklear.h:4198
struct nk_color color
Definition: nuklear.h:4199
Definition: nuklear.h:4295
struct nk_vec2i points[1]
Definition: nuklear.h:4299
unsigned short point_count
Definition: nuklear.h:4298
struct nk_color color
Definition: nuklear.h:4297
struct nk_command header
Definition: nuklear.h:4296
Definition: nuklear.h:4287
struct nk_command header
Definition: nuklear.h:4288
unsigned short line_thickness
Definition: nuklear.h:4290
unsigned short point_count
Definition: nuklear.h:4291
struct nk_color color
Definition: nuklear.h:4289
struct nk_vec2i points[1]
Definition: nuklear.h:4292
Definition: nuklear.h:4302
unsigned short line_thickness
Definition: nuklear.h:4305
struct nk_vec2i points[1]
Definition: nuklear.h:4307
struct nk_color color
Definition: nuklear.h:4304
struct nk_command header
Definition: nuklear.h:4303
unsigned short point_count
Definition: nuklear.h:4306
Definition: nuklear.h:4220
short x
Definition: nuklear.h:4223
struct nk_command header
Definition: nuklear.h:4221
short y
Definition: nuklear.h:4223
unsigned short w
Definition: nuklear.h:4224
unsigned short rounding
Definition: nuklear.h:4222
unsigned short h
Definition: nuklear.h:4224
struct nk_color color
Definition: nuklear.h:4225
Definition: nuklear.h:4228
struct nk_command header
Definition: nuklear.h:4229
struct nk_color top
Definition: nuklear.h:4233
struct nk_color left
Definition: nuklear.h:4232
struct nk_color right
Definition: nuklear.h:4235
short y
Definition: nuklear.h:4230
unsigned short h
Definition: nuklear.h:4231
struct nk_color bottom
Definition: nuklear.h:4234
short x
Definition: nuklear.h:4230
unsigned short w
Definition: nuklear.h:4231
Definition: nuklear.h:4211
short y
Definition: nuklear.h:4215
unsigned short h
Definition: nuklear.h:4216
struct nk_color color
Definition: nuklear.h:4217
unsigned short w
Definition: nuklear.h:4216
unsigned short rounding
Definition: nuklear.h:4213
unsigned short line_thickness
Definition: nuklear.h:4214
struct nk_command header
Definition: nuklear.h:4212
short x
Definition: nuklear.h:4215
Definition: nuklear.h:4188
short y
Definition: nuklear.h:4190
unsigned short h
Definition: nuklear.h:4191
unsigned short w
Definition: nuklear.h:4191
struct nk_command header
Definition: nuklear.h:4189
short x
Definition: nuklear.h:4190
Definition: nuklear.h:4328
char string[1]
Definition: nuklear.h:4337
struct nk_color background
Definition: nuklear.h:4331
const struct nk_user_font * font
Definition: nuklear.h:4330
struct nk_command header
Definition: nuklear.h:4329
int length
Definition: nuklear.h:4336
struct nk_color foreground
Definition: nuklear.h:4332
short x
Definition: nuklear.h:4333
float height
Definition: nuklear.h:4335
short y
Definition: nuklear.h:4333
unsigned short h
Definition: nuklear.h:4334
unsigned short w
Definition: nuklear.h:4334
Definition: nuklear.h:4247
struct nk_vec2i b
Definition: nuklear.h:4250
struct nk_vec2i c
Definition: nuklear.h:4251
struct nk_command header
Definition: nuklear.h:4248
struct nk_vec2i a
Definition: nuklear.h:4249
struct nk_color color
Definition: nuklear.h:4252
Definition: nuklear.h:4238
unsigned short line_thickness
Definition: nuklear.h:4240
struct nk_vec2i a
Definition: nuklear.h:4241
struct nk_vec2i b
Definition: nuklear.h:4242
struct nk_vec2i c
Definition: nuklear.h:4243
struct nk_color color
Definition: nuklear.h:4244
struct nk_command header
Definition: nuklear.h:4239
Definition: nuklear.h:4180
enum nk_command_type type
Definition: nuklear.h:4181
nk_size next
Definition: nuklear.h:4182
Definition: nuklear.h:5299
struct nk_config_stack_vec2 vectors
Definition: nuklear.h:5302
struct nk_config_stack_flags flags
Definition: nuklear.h:5303
struct nk_config_stack_style_item style_items
Definition: nuklear.h:5300
struct nk_config_stack_color colors
Definition: nuklear.h:5304
struct nk_config_stack_float floats
Definition: nuklear.h:5301
struct nk_config_stack_button_behavior button_behaviors
Definition: nuklear.h:5306
struct nk_config_stack_user_font fonts
Definition: nuklear.h:5305
Definition: nuklear.h:5352
int build
Definition: nuklear.h:5381
int use_pool
Definition: nuklear.h:5382
nk_flags last_widget_state
Definition: nuklear.h:5358
enum nk_button_behavior button_behavior
Definition: nuklear.h:5359
unsigned int count
Definition: nuklear.h:5389
struct nk_style style
Definition: nuklear.h:5355
float delta_time_seconds
Definition: nuklear.h:5361
struct nk_window * begin
Definition: nuklear.h:5384
unsigned int seq
Definition: nuklear.h:5390
struct nk_window * current
Definition: nuklear.h:5387
struct nk_buffer memory
Definition: nuklear.h:5356
struct nk_window * end
Definition: nuklear.h:5385
struct nk_clipboard clip
Definition: nuklear.h:5357
struct nk_pool pool
Definition: nuklear.h:5383
struct nk_configuration_stacks stacks
Definition: nuklear.h:5360
struct nk_page_element * freelist
Definition: nuklear.h:5388
struct nk_window * active
Definition: nuklear.h:5386
struct nk_input input
Definition: nuklear.h:5354
struct nk_text_edit text_edit
Definition: nuklear.h:5376
struct nk_command_buffer overlay
Definition: nuklear.h:5378
Definition: nuklear.h:937
enum nk_anti_aliasing shape_AA
Definition: nuklear.h:940
enum nk_anti_aliasing line_AA
Definition: nuklear.h:939
nk_size vertex_alignment
Definition: nuklear.h:947
nk_size vertex_size
Definition: nuklear.h:946
float global_alpha
Definition: nuklear.h:938
const struct nk_draw_vertex_layout_element * vertex_layout
Definition: nuklear.h:945
unsigned arc_segment_count
Definition: nuklear.h:942
unsigned circle_segment_count
Definition: nuklear.h:941
struct nk_draw_null_texture null
Definition: nuklear.h:944
unsigned curve_segment_count
Definition: nuklear.h:943
Definition: nuklear.h:249
struct nk_vec2 size offset
Definition: nuklear.h:249
struct nk_image img
Definition: nuklear.h:249
Definition: nuklear.h:933
nk_handle texture
Definition: nuklear.h:934
struct nk_vec2 uv
Definition: nuklear.h:935
Definition: nuklear.h:5165
unsigned int seq
Definition: nuklear.h:5167
int active
Definition: nuklear.h:5169
int sel_end
Definition: nuklear.h:5172
nk_hash name
Definition: nuklear.h:5166
int prev
Definition: nuklear.h:5169
unsigned char single_line
Definition: nuklear.h:5175
int cursor
Definition: nuklear.h:5170
unsigned int old
Definition: nuklear.h:5168
unsigned char mode
Definition: nuklear.h:5174
int sel_start
Definition: nuklear.h:5171
struct nk_scroll scrollbar
Definition: nuklear.h:5173
Definition: nuklear.h:248
unsigned short region[4]
Definition: nuklear.h:248
unsigned short h
Definition: nuklear.h:248
unsigned short w
Definition: nuklear.h:248
nk_handle handle
Definition: nuklear.h:248
Definition: nuklear.h:4408
struct nk_keyboard keyboard
Definition: nuklear.h:4409
struct nk_mouse mouse
Definition: nuklear.h:4410
Definition: nuklear.h:4398
unsigned int clicked
Definition: nuklear.h:4400
int down
Definition: nuklear.h:4399
Definition: nuklear.h:4402
int text_len
Definition: nuklear.h:4405
struct nk_key keys[NK_KEY_MAX]
Definition: nuklear.h:4403
char text[NK_INPUT_MAX]
Definition: nuklear.h:4404
Definition: nuklear.h:2808
nk_uint scroll_value
Definition: nuklear.h:2815
int end
Definition: nuklear.h:2810
int count
Definition: nuklear.h:2810
int begin
Definition: nuklear.h:2810
nk_uint * scroll_pointer
Definition: nuklear.h:2814
int total_height
Definition: nuklear.h:2812
struct nk_context * ctx
Definition: nuklear.h:2813
Definition: nuklear.h:3875
nk_size needed
Definition: nuklear.h:3880
nk_size allocated
Definition: nuklear.h:3879
void * memory
Definition: nuklear.h:3876
unsigned int type
Definition: nuklear.h:3877
nk_size calls
Definition: nuklear.h:3881
nk_size size
Definition: nuklear.h:3878
Definition: nuklear.h:3900
nk_size size
Definition: nuklear.h:3900
void * ptr
Definition: nuklear.h:3900
Definition: nuklear.h:5103
float w
Definition: nuklear.h:5104
float y
Definition: nuklear.h:5104
struct nk_scroll offset
Definition: nuklear.h:5105
float x
Definition: nuklear.h:5104
float h
Definition: nuklear.h:5104
Definition: nuklear.h:4382
unsigned int clicked
Definition: nuklear.h:4384
struct nk_vec2 clicked_pos
Definition: nuklear.h:4385
int down
Definition: nuklear.h:4383
Definition: nuklear.h:4387
struct nk_vec2 pos
Definition: nuklear.h:4389
struct nk_mouse_button buttons[NK_BUTTON_MAX]
Definition: nuklear.h:4388
unsigned char ungrab
Definition: nuklear.h:4395
unsigned char grabbed
Definition: nuklear.h:4394
struct nk_vec2 scroll_delta
Definition: nuklear.h:4392
unsigned char grab
Definition: nuklear.h:4393
struct nk_vec2 delta
Definition: nuklear.h:4391
struct nk_vec2 prev
Definition: nuklear.h:4390
Definition: nuklear.h:5329
union nk_page_data data
Definition: nuklear.h:5330
struct nk_page_element * prev
Definition: nuklear.h:5332
struct nk_page_element * next
Definition: nuklear.h:5331
Definition: nuklear.h:5335
struct nk_page * next
Definition: nuklear.h:5337
struct nk_page_element win[1]
Definition: nuklear.h:5338
unsigned int size
Definition: nuklear.h:5336
Definition: nuklear.h:5108
float border
Definition: nuklear.h:5117
enum nk_panel_type type
Definition: nuklear.h:5109
nk_uint * offset_x
Definition: nuklear.h:5112
struct nk_menu_state menu
Definition: nuklear.h:5120
float at_y
Definition: nuklear.h:5114
struct nk_chart chart
Definition: nuklear.h:5122
nk_flags flags
Definition: nuklear.h:5110
struct nk_rect clip
Definition: nuklear.h:5119
nk_uint * offset_y
Definition: nuklear.h:5113
float at_x
Definition: nuklear.h:5114
struct nk_row_layout row
Definition: nuklear.h:5121
unsigned int has_scrolling
Definition: nuklear.h:5118
float footer_height
Definition: nuklear.h:5115
struct nk_rect bounds
Definition: nuklear.h:5111
float max_x
Definition: nuklear.h:5114
struct nk_command_buffer * buffer
Definition: nuklear.h:5123
struct nk_panel * parent
Definition: nuklear.h:5124
float header_height
Definition: nuklear.h:5116
Definition: nuklear.h:5341
struct nk_allocator alloc
Definition: nuklear.h:5342
unsigned int page_count
Definition: nuklear.h:5344
nk_size size
Definition: nuklear.h:5348
struct nk_page_element * freelist
Definition: nuklear.h:5346
nk_size cap
Definition: nuklear.h:5349
unsigned capacity
Definition: nuklear.h:5347
enum nk_allocation_type type
Definition: nuklear.h:5343
struct nk_page * pages
Definition: nuklear.h:5345
Definition: nuklear.h:5095
int active
Definition: nuklear.h:5100
nk_size end
Definition: nuklear.h:5099
nk_size last
Definition: nuklear.h:5098
nk_size begin
Definition: nuklear.h:5096
nk_size parent
Definition: nuklear.h:5097
Definition: nuklear.h:5153
struct nk_rect header
Definition: nuklear.h:5162
unsigned con_old
Definition: nuklear.h:5160
struct nk_popup_buffer buf
Definition: nuklear.h:5156
unsigned combo_count
Definition: nuklear.h:5159
nk_hash name
Definition: nuklear.h:5157
struct nk_window * win
Definition: nuklear.h:5154
unsigned con_count
Definition: nuklear.h:5160
enum nk_panel_type type
Definition: nuklear.h:5155
unsigned active_con
Definition: nuklear.h:5161
int active
Definition: nuklear.h:5158
Definition: nuklear.h:5178
unsigned int seq
Definition: nuklear.h:5186
int cursor
Definition: nuklear.h:5182
unsigned int old
Definition: nuklear.h:5187
int select_end
Definition: nuklear.h:5184
int select_start
Definition: nuklear.h:5183
nk_hash name
Definition: nuklear.h:5185
int active
Definition: nuklear.h:5179
int length
Definition: nuklear.h:5181
char buffer[NK_MAX_NUMBER_BUFFER]
Definition: nuklear.h:5180
int prev
Definition: nuklear.h:5179
int state
Definition: nuklear.h:5188
Definition: nuklear.h:244
float h
Definition: nuklear.h:244
float x
Definition: nuklear.h:244
float y
Definition: nuklear.h:244
float w
Definition: nuklear.h:244
Definition: nuklear.h:245
short h
Definition: nuklear.h:245
short w
Definition: nuklear.h:245
short y
Definition: nuklear.h:245
short x
Definition: nuklear.h:245
Definition: nuklear.h:5079
float height
Definition: nuklear.h:5082
float filled
Definition: nuklear.h:5089
int columns
Definition: nuklear.h:5084
int index
Definition: nuklear.h:5081
enum nk_panel_row_layout_type type
Definition: nuklear.h:5080
float min_height
Definition: nuklear.h:5083
int tree_depth
Definition: nuklear.h:5091
float item_height
Definition: nuklear.h:5087
float item_width
Definition: nuklear.h:5086
struct nk_rect item
Definition: nuklear.h:5090
float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]
Definition: nuklear.h:5092
const float * ratio
Definition: nuklear.h:5085
float item_offset
Definition: nuklear.h:5088
Definition: nuklear.h:250
nk_uint y
Definition: nuklear.h:250
nk_uint x
Definition: nuklear.h:250
Definition: nuklear.h:3947
int len
Definition: nuklear.h:3949
struct nk_buffer buffer
Definition: nuklear.h:3948
Definition: nuklear.h:4608
struct nk_color text_background
Definition: nuklear.h:4616
void(* draw_end)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:4632
float border
Definition: nuklear.h:4623
struct nk_color text_active
Definition: nuklear.h:4619
nk_flags text_alignment
Definition: nuklear.h:4620
struct nk_vec2 padding
Definition: nuklear.h:4625
nk_handle userdata
Definition: nuklear.h:4630
struct nk_style_item normal
Definition: nuklear.h:4610
struct nk_style_item active
Definition: nuklear.h:4612
struct nk_vec2 touch_padding
Definition: nuklear.h:4627
struct nk_color text_normal
Definition: nuklear.h:4617
struct nk_style_item hover
Definition: nuklear.h:4611
struct nk_color text_hover
Definition: nuklear.h:4618
void(* draw_begin)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:4631
struct nk_color border_color
Definition: nuklear.h:4613
struct nk_vec2 image_padding
Definition: nuklear.h:4626
float rounding
Definition: nuklear.h:4624
Definition: nuklear.h:4863
float rounding
Definition: nuklear.h:4872
struct nk_color border_color
Definition: nuklear.h:4866
struct nk_style_item background
Definition: nuklear.h:4865
float border
Definition: nuklear.h:4871
struct nk_vec2 padding
Definition: nuklear.h:4873
struct nk_color selected_color
Definition: nuklear.h:4867
struct nk_color color
Definition: nuklear.h:4868
Definition: nuklear.h:4876
struct nk_color label_active
Definition: nuklear.h:4886
struct nk_vec2 content_padding
Definition: nuklear.h:4902
struct nk_color label_normal
Definition: nuklear.h:4884
struct nk_style_item normal
Definition: nuklear.h:4878
struct nk_color border_color
Definition: nuklear.h:4881
struct nk_style_button button
Definition: nuklear.h:4894
enum nk_symbol_type sym_active
Definition: nuklear.h:4897
float border
Definition: nuklear.h:4900
struct nk_style_item hover
Definition: nuklear.h:4879
enum nk_symbol_type sym_hover
Definition: nuklear.h:4896
struct nk_vec2 spacing
Definition: nuklear.h:4904
struct nk_color symbol_active
Definition: nuklear.h:4891
struct nk_style_item active
Definition: nuklear.h:4880
enum nk_symbol_type sym_normal
Definition: nuklear.h:4895
struct nk_color label_hover
Definition: nuklear.h:4885
float rounding
Definition: nuklear.h:4901
struct nk_vec2 button_padding
Definition: nuklear.h:4903
struct nk_color symbol_normal
Definition: nuklear.h:4889
struct nk_color symbol_hover
Definition: nuklear.h:4890
Definition: nuklear.h:4798
struct nk_style_item active
Definition: nuklear.h:4802
struct nk_color selected_normal
Definition: nuklear.h:4818
struct nk_color cursor_normal
Definition: nuklear.h:4807
struct nk_color selected_text_hover
Definition: nuklear.h:4821
struct nk_style_scrollbar scrollbar
Definition: nuklear.h:4804
float border
Definition: nuklear.h:4824
float cursor_size
Definition: nuklear.h:4826
struct nk_color text_hover
Definition: nuklear.h:4814
struct nk_color border_color
Definition: nuklear.h:4803
struct nk_vec2 padding
Definition: nuklear.h:4828
struct nk_color cursor_text_normal
Definition: nuklear.h:4809
float rounding
Definition: nuklear.h:4825
struct nk_vec2 scrollbar_size
Definition: nuklear.h:4827
struct nk_color selected_hover
Definition: nuklear.h:4819
struct nk_color selected_text_normal
Definition: nuklear.h:4820
struct nk_color cursor_hover
Definition: nuklear.h:4808
struct nk_color text_active
Definition: nuklear.h:4815
struct nk_color text_normal
Definition: nuklear.h:4813
struct nk_style_item normal
Definition: nuklear.h:4800
float row_padding
Definition: nuklear.h:4829
struct nk_color cursor_text_hover
Definition: nuklear.h:4810
struct nk_style_item hover
Definition: nuklear.h:4801
Definition: nuklear.h:4598
enum nk_style_item_type type
Definition: nuklear.h:4599
union nk_style_item_data data
Definition: nuklear.h:4600
Definition: nuklear.h:4739
float rounding
Definition: nuklear.h:4753
struct nk_style_item normal
Definition: nuklear.h:4741
struct nk_color cursor_border_color
Definition: nuklear.h:4750
struct nk_color border_color
Definition: nuklear.h:4744
struct nk_style_item cursor_hover
Definition: nuklear.h:4748
float cursor_border
Definition: nuklear.h:4755
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4762
struct nk_style_item cursor_normal
Definition: nuklear.h:4747
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4761
struct nk_style_item cursor_active
Definition: nuklear.h:4749
struct nk_vec2 padding
Definition: nuklear.h:4757
float cursor_rounding
Definition: nuklear.h:4756
struct nk_style_item active
Definition: nuklear.h:4743
struct nk_style_item hover
Definition: nuklear.h:4742
float border
Definition: nuklear.h:4754
nk_handle userdata
Definition: nuklear.h:4760
Definition: nuklear.h:4832
enum nk_symbol_type sym_left
Definition: nuklear.h:4845
struct nk_style_button dec_button
Definition: nuklear.h:4855
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4859
nk_handle userdata
Definition: nuklear.h:4858
struct nk_style_item active
Definition: nuklear.h:4836
struct nk_style_edit edit
Definition: nuklear.h:4853
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4860
enum nk_symbol_type sym_right
Definition: nuklear.h:4846
struct nk_color label_hover
Definition: nuklear.h:4841
struct nk_color border_color
Definition: nuklear.h:4837
struct nk_color label_normal
Definition: nuklear.h:4840
float rounding
Definition: nuklear.h:4850
struct nk_style_item normal
Definition: nuklear.h:4834
struct nk_color label_active
Definition: nuklear.h:4842
float border
Definition: nuklear.h:4849
struct nk_vec2 padding
Definition: nuklear.h:4851
struct nk_style_button inc_button
Definition: nuklear.h:4854
struct nk_style_item hover
Definition: nuklear.h:4835
Definition: nuklear.h:4765
struct nk_style_button dec_button
Definition: nuklear.h:4788
struct nk_style_button inc_button
Definition: nuklear.h:4787
struct nk_style_item normal
Definition: nuklear.h:4767
struct nk_vec2 padding
Definition: nuklear.h:4783
int show_buttons
Definition: nuklear.h:4786
float border
Definition: nuklear.h:4779
struct nk_style_item hover
Definition: nuklear.h:4768
struct nk_style_item cursor_normal
Definition: nuklear.h:4773
float rounding
Definition: nuklear.h:4780
struct nk_style_item cursor_hover
Definition: nuklear.h:4774
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4794
struct nk_color cursor_border_color
Definition: nuklear.h:4776
float rounding_cursor
Definition: nuklear.h:4782
struct nk_style_item active
Definition: nuklear.h:4769
struct nk_style_item cursor_active
Definition: nuklear.h:4775
float border_cursor
Definition: nuklear.h:4781
nk_handle userdata
Definition: nuklear.h:4793
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4795
enum nk_symbol_type dec_symbol
Definition: nuklear.h:4790
struct nk_color border_color
Definition: nuklear.h:4770
enum nk_symbol_type inc_symbol
Definition: nuklear.h:4789
Definition: nuklear.h:4665
struct nk_color text_hover
Definition: nuklear.h:4678
float rounding
Definition: nuklear.h:4689
struct nk_vec2 padding
Definition: nuklear.h:4690
struct nk_style_item hover
Definition: nuklear.h:4668
struct nk_style_item hover_active
Definition: nuklear.h:4673
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4696
struct nk_color text_hover_active
Definition: nuklear.h:4683
struct nk_color text_normal
Definition: nuklear.h:4677
struct nk_vec2 image_padding
Definition: nuklear.h:4692
struct nk_vec2 touch_padding
Definition: nuklear.h:4691
struct nk_style_item normal_active
Definition: nuklear.h:4672
nk_handle userdata
Definition: nuklear.h:4695
struct nk_style_item normal
Definition: nuklear.h:4667
struct nk_color text_normal_active
Definition: nuklear.h:4682
nk_flags text_alignment
Definition: nuklear.h:4686
struct nk_color text_pressed
Definition: nuklear.h:4679
struct nk_style_item pressed
Definition: nuklear.h:4669
struct nk_color text_pressed_active
Definition: nuklear.h:4684
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4697
struct nk_style_item pressed_active
Definition: nuklear.h:4674
struct nk_color text_background
Definition: nuklear.h:4685
Definition: nuklear.h:4700
int show_buttons
Definition: nuklear.h:4727
struct nk_style_item cursor_active
Definition: nuklear.h:4716
struct nk_color bar_normal
Definition: nuklear.h:4708
struct nk_style_item cursor_normal
Definition: nuklear.h:4714
struct nk_vec2 spacing
Definition: nuklear.h:4723
struct nk_color border_color
Definition: nuklear.h:4705
struct nk_style_button dec_button
Definition: nuklear.h:4729
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4735
struct nk_style_item normal
Definition: nuklear.h:4702
float bar_height
Definition: nuklear.h:4721
struct nk_color bar_active
Definition: nuklear.h:4710
enum nk_symbol_type dec_symbol
Definition: nuklear.h:4731
struct nk_color bar_hover
Definition: nuklear.h:4709
nk_handle userdata
Definition: nuklear.h:4734
struct nk_style_button inc_button
Definition: nuklear.h:4728
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4736
enum nk_symbol_type inc_symbol
Definition: nuklear.h:4730
struct nk_vec2 padding
Definition: nuklear.h:4722
float rounding
Definition: nuklear.h:4720
struct nk_style_item hover
Definition: nuklear.h:4703
struct nk_style_item active
Definition: nuklear.h:4704
struct nk_color bar_filled
Definition: nuklear.h:4711
struct nk_style_item cursor_hover
Definition: nuklear.h:4715
struct nk_vec2 cursor_size
Definition: nuklear.h:4724
float border
Definition: nuklear.h:4719
Definition: nuklear.h:4907
struct nk_style_button node_maximize_button
Definition: nuklear.h:4916
struct nk_style_button tab_minimize_button
Definition: nuklear.h:4915
struct nk_style_button tab_maximize_button
Definition: nuklear.h:4914
enum nk_symbol_type sym_minimize
Definition: nuklear.h:4918
float indent
Definition: nuklear.h:4924
enum nk_symbol_type sym_maximize
Definition: nuklear.h:4919
float border
Definition: nuklear.h:4922
struct nk_style_item background
Definition: nuklear.h:4909
struct nk_style_button node_minimize_button
Definition: nuklear.h:4917
float rounding
Definition: nuklear.h:4923
struct nk_vec2 spacing
Definition: nuklear.h:4926
struct nk_color text
Definition: nuklear.h:4911
struct nk_color border_color
Definition: nuklear.h:4910
struct nk_vec2 padding
Definition: nuklear.h:4925
Definition: nuklear.h:4603
struct nk_vec2 padding
Definition: nuklear.h:4605
struct nk_color color
Definition: nuklear.h:4604
Definition: nuklear.h:4635
struct nk_style_item cursor_hover
Definition: nuklear.h:4644
struct nk_vec2 padding
Definition: nuklear.h:4654
struct nk_style_item hover
Definition: nuklear.h:4638
struct nk_color text_normal
Definition: nuklear.h:4647
struct nk_color border_color
Definition: nuklear.h:4640
struct nk_style_item cursor_normal
Definition: nuklear.h:4643
struct nk_color text_active
Definition: nuklear.h:4649
struct nk_style_item normal
Definition: nuklear.h:4637
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4662
struct nk_style_item active
Definition: nuklear.h:4639
struct nk_vec2 touch_padding
Definition: nuklear.h:4655
nk_flags text_alignment
Definition: nuklear.h:4651
struct nk_color text_hover
Definition: nuklear.h:4648
float border
Definition: nuklear.h:4657
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4661
nk_handle userdata
Definition: nuklear.h:4660
struct nk_color text_background
Definition: nuklear.h:4650
float spacing
Definition: nuklear.h:4656
Definition: nuklear.h:4933
struct nk_style_button close_button
Definition: nuklear.h:4940
enum nk_symbol_type close_symbol
Definition: nuklear.h:4942
struct nk_style_button minimize_button
Definition: nuklear.h:4941
struct nk_vec2 padding
Definition: nuklear.h:4953
struct nk_vec2 spacing
Definition: nuklear.h:4955
struct nk_style_item active
Definition: nuklear.h:4937
struct nk_style_item normal
Definition: nuklear.h:4935
struct nk_color label_hover
Definition: nuklear.h:4948
struct nk_color label_active
Definition: nuklear.h:4949
struct nk_color label_normal
Definition: nuklear.h:4947
enum nk_symbol_type minimize_symbol
Definition: nuklear.h:4943
enum nk_style_header_align align
Definition: nuklear.h:4952
enum nk_symbol_type maximize_symbol
Definition: nuklear.h:4944
struct nk_style_item hover
Definition: nuklear.h:4936
struct nk_vec2 label_padding
Definition: nuklear.h:4954
Definition: nuklear.h:4958
float group_border
Definition: nuklear.h:4976
struct nk_style_item fixed_background
Definition: nuklear.h:4960
struct nk_style_item scaler
Definition: nuklear.h:4970
struct nk_color background
Definition: nuklear.h:4961
struct nk_vec2 menu_padding
Definition: nuklear.h:4991
struct nk_color popup_border_color
Definition: nuklear.h:4964
float menu_border
Definition: nuklear.h:4975
struct nk_vec2 scrollbar_size
Definition: nuklear.h:4983
struct nk_vec2 tooltip_padding
Definition: nuklear.h:4992
struct nk_color group_border_color
Definition: nuklear.h:4968
struct nk_vec2 padding
Definition: nuklear.h:4986
struct nk_color combo_border_color
Definition: nuklear.h:4965
struct nk_color border_color
Definition: nuklear.h:4963
float combo_border
Definition: nuklear.h:4973
float min_row_height_padding
Definition: nuklear.h:4979
struct nk_vec2 combo_padding
Definition: nuklear.h:4989
struct nk_vec2 group_padding
Definition: nuklear.h:4987
struct nk_vec2 popup_padding
Definition: nuklear.h:4988
struct nk_vec2 spacing
Definition: nuklear.h:4982
float tooltip_border
Definition: nuklear.h:4977
float rounding
Definition: nuklear.h:4981
struct nk_color contextual_border_color
Definition: nuklear.h:4966
struct nk_style_window_header header
Definition: nuklear.h:4959
float contextual_border
Definition: nuklear.h:4974
struct nk_color tooltip_border_color
Definition: nuklear.h:4969
struct nk_vec2 contextual_padding
Definition: nuklear.h:4990
float border
Definition: nuklear.h:4972
struct nk_color menu_border_color
Definition: nuklear.h:4967
struct nk_vec2 min_size
Definition: nuklear.h:4984
float popup_border
Definition: nuklear.h:4978
Definition: nuklear.h:4995
struct nk_style_scrollbar scrollv
Definition: nuklear.h:5015
struct nk_style_toggle option
Definition: nuklear.h:5006
struct nk_style_button contextual_button
Definition: nuklear.h:5004
struct nk_style_edit edit
Definition: nuklear.h:5012
struct nk_style_text text
Definition: nuklear.h:5002
struct nk_style_scrollbar scrollh
Definition: nuklear.h:5014
struct nk_style_button button
Definition: nuklear.h:5003
struct nk_style_tab tab
Definition: nuklear.h:5016
struct nk_style_chart chart
Definition: nuklear.h:5013
struct nk_style_property property
Definition: nuklear.h:5011
struct nk_style_selectable selectable
Definition: nuklear.h:5008
struct nk_style_progress progress
Definition: nuklear.h:5010
struct nk_cursor * cursor_last
Definition: nuklear.h:4999
int cursor_visible
Definition: nuklear.h:5000
const struct nk_user_font * font
Definition: nuklear.h:4996
const struct nk_cursor * cursors[NK_CURSOR_COUNT]
Definition: nuklear.h:4997
struct nk_style_window window
Definition: nuklear.h:5018
struct nk_style_slider slider
Definition: nuklear.h:5009
const struct nk_cursor * cursor_active
Definition: nuklear.h:4998
struct nk_style_combo combo
Definition: nuklear.h:5017
struct nk_style_button menu_button
Definition: nuklear.h:5005
struct nk_style_toggle checkbox
Definition: nuklear.h:5007
Definition: nuklear.h:5315
unsigned int size
Definition: nuklear.h:5317
struct nk_table * next
Definition: nuklear.h:5320
unsigned int seq
Definition: nuklear.h:5316
nk_hash keys[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:5318
nk_uint values[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:5319
struct nk_table * prev
Definition: nuklear.h:5320
Definition: nuklear.h:4063
struct nk_str string
Definition: nuklear.h:4065
int select_end
Definition: nuklear.h:4071
struct nk_vec2 scrollbar
Definition: nuklear.h:4067
unsigned char active
Definition: nuklear.h:4077
unsigned char has_preferred_x
Definition: nuklear.h:4075
int cursor
Definition: nuklear.h:4069
unsigned char initialized
Definition: nuklear.h:4074
unsigned char single_line
Definition: nuklear.h:4076
unsigned char mode
Definition: nuklear.h:4072
float preferred_x
Definition: nuklear.h:4079
unsigned char cursor_at_end_of_line
Definition: nuklear.h:4073
struct nk_clipboard clip
Definition: nuklear.h:4064
unsigned char padding1
Definition: nuklear.h:4078
nk_plugin_filter filter
Definition: nuklear.h:4066
struct nk_text_undo_state undo
Definition: nuklear.h:4080
int select_start
Definition: nuklear.h:4070
Definition: nuklear.h:4036
int where
Definition: nuklear.h:4037
short delete_length
Definition: nuklear.h:4039
short char_storage
Definition: nuklear.h:4040
short insert_length
Definition: nuklear.h:4038
Definition: nuklear.h:4043
nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]
Definition: nuklear.h:4045
short undo_char_point
Definition: nuklear.h:4048
short redo_point
Definition: nuklear.h:4047
short undo_point
Definition: nuklear.h:4046
short redo_char_point
Definition: nuklear.h:4049
struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]
Definition: nuklear.h:4044
Definition: nuklear.h:3697
nk_handle userdata
Definition: nuklear.h:3698
nk_text_width_f width
Definition: nuklear.h:3702
float height
Definition: nuklear.h:3700
Definition: nuklear.h:242
float x
Definition: nuklear.h:242
float y
Definition: nuklear.h:242
Definition: nuklear.h:243
short y
Definition: nuklear.h:243
short x
Definition: nuklear.h:243
Definition: nuklear.h:5191
unsigned int table_count
Definition: nuklear.h:5210
struct nk_rect bounds
Definition: nuklear.h:5197
struct nk_window * next
Definition: nuklear.h:5213
struct nk_window * prev
Definition: nuklear.h:5214
struct nk_table * tables
Definition: nuklear.h:5209
char name_string[NK_WINDOW_MAX_NAME]
Definition: nuklear.h:5194
struct nk_edit_state edit
Definition: nuklear.h:5206
struct nk_scroll scrollbar
Definition: nuklear.h:5198
struct nk_popup_state popup
Definition: nuklear.h:5205
struct nk_command_buffer buffer
Definition: nuklear.h:5199
nk_flags flags
Definition: nuklear.h:5195
struct nk_property_state property
Definition: nuklear.h:5204
unsigned int seq
Definition: nuklear.h:5192
struct nk_panel * layout
Definition: nuklear.h:5200
struct nk_window * parent
Definition: nuklear.h:5215
unsigned int scrolled
Definition: nuklear.h:5207
float scrollbar_hiding_timer
Definition: nuklear.h:5201
nk_hash name
Definition: nuklear.h:5193
Definition: nuklear.h:247
int id
Definition: nuklear.h:247
void * ptr
Definition: nuklear.h:247
Definition: nuklear.h:5323
struct nk_table tbl
Definition: nuklear.h:5324
struct nk_panel pan
Definition: nuklear.h:5325
struct nk_window win
Definition: nuklear.h:5326
Definition: nuklear.h:4593
struct nk_color color
Definition: nuklear.h:4595
struct nk_image image
Definition: nuklear.h:4594